Compare commits
1 Commits
642340498f
...
7ac6719aa9
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 7ac6719aa9 |
|
@ -5,6 +5,4 @@ db.json
|
||||||
node_modules/
|
node_modules/
|
||||||
public/
|
public/
|
||||||
.deploy*/
|
.deploy*/
|
||||||
_multiconfig.yml
|
_multiconfig.yml
|
||||||
.vscode
|
|
||||||
.idea/*
|
|
|
@ -202,8 +202,8 @@ website_count:
|
||||||
analytics:
|
analytics:
|
||||||
umami:
|
umami:
|
||||||
umami_enable : true
|
umami_enable : true
|
||||||
umami_src: "https://umami.lianglianglee.com/script.js"
|
umami_src: "http://analyze.lianglianglee.com/umami.js"
|
||||||
umami_data_id: "c45fa8bb-5a87-4991-975c-b53e8224b33c"
|
umami_data_id: "17ea0407-527d-4c0b-ae64-3bdf28f5678a"
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
# Local Search
|
# Local Search
|
||||||
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/local_search.html
|
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/local_search.html
|
||||||
|
@ -220,7 +220,7 @@ local_search:
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
comment:
|
comment:
|
||||||
enable: false # Option values: true | false
|
enable: false # Option values: true | false
|
||||||
use: artalk # Option values: valine | gitalk | twikoo | waline | artalk
|
use: valine # Option values: valine | gitalk | twikoo | waline
|
||||||
|
|
||||||
# Valine
|
# Valine
|
||||||
# See: https://github.com/xCss/Valine
|
# See: https://github.com/xCss/Valine
|
||||||
|
@ -257,9 +257,7 @@ comment:
|
||||||
server_url: # Server URL
|
server_url: # Server URL
|
||||||
reaction: false # Article reactions, Option values: true | false
|
reaction: false # Article reactions, Option values: true | false
|
||||||
version: 2 # Waline version, default use v2
|
version: 2 # Waline version, default use v2
|
||||||
artalk:
|
|
||||||
server:
|
|
||||||
site:
|
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
# RSS
|
# RSS
|
||||||
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/rss.html
|
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/rss.html
|
||||||
|
@ -296,7 +294,7 @@ pjax:
|
||||||
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/footer.html
|
# Docs: https://keep-docs.xpoet.cn/tutorial/configuration-guide/footer.html
|
||||||
# ---------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------
|
||||||
footer:
|
footer:
|
||||||
since: 2024 # The starting year of your website, Can be null
|
since: 2023 # The starting year of your website, Can be null
|
||||||
icp: # ICP record number of your website, Can be null
|
icp: # ICP record number of your website, Can be null
|
||||||
site_deploy:
|
site_deploy:
|
||||||
enable: false # Option values: true | false
|
enable: false # Option values: true | false
|
||||||
|
|
30
_config.yml
30
_config.yml
|
@ -14,24 +14,12 @@ timezone: 'Asia/Shanghai'
|
||||||
# URL
|
# URL
|
||||||
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
|
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
|
||||||
url: https://blog.lianglianglee.com
|
url: https://blog.lianglianglee.com
|
||||||
permalink: posts/:abbrlink.html
|
permalink: :year/:month/:day/:title/
|
||||||
permalink_defaults:
|
permalink_defaults:
|
||||||
pretty_urls:
|
pretty_urls:
|
||||||
trailing_index: false # Set to false to remove trailing 'index.html' from permalinks
|
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
|
||||||
trailing_html: false # Set to false to remove trailing '.html' from permalinks
|
trailing_html: true # Set to false to remove trailing '.html' from permalinks
|
||||||
abbrlink:
|
|
||||||
alg: crc32 #支持crc16和crc32算法(默认crc16)
|
|
||||||
rep: hex #支持dec和hex值(默认dec)
|
|
||||||
drafts: false #(true)Process draft,(false)Do not process draft. false(default)
|
|
||||||
# Generate categories from directory-tree
|
|
||||||
# depth: the max_depth of directory-tree you want to generate, should > 0
|
|
||||||
auto_category:
|
|
||||||
enable: true #true(default)
|
|
||||||
depth: #3(default)
|
|
||||||
over_write: false
|
|
||||||
auto_title: false #enable auto title, it can auto fill the title by path
|
|
||||||
auto_date: false #enable auto date, it can auto fill the date by time today
|
|
||||||
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink.
|
|
||||||
# Directory
|
# Directory
|
||||||
source_dir: source
|
source_dir: source
|
||||||
public_dir: public
|
public_dir: public
|
||||||
|
@ -121,15 +109,9 @@ search:
|
||||||
content: true
|
content: true
|
||||||
format: striptags
|
format: striptags
|
||||||
feed:
|
feed:
|
||||||
type:
|
type: atom
|
||||||
- atom
|
path: atom.xml
|
||||||
- rss2
|
|
||||||
path:
|
|
||||||
- atom.xml
|
|
||||||
- rss2.xml
|
|
||||||
limit: 20
|
limit: 20
|
||||||
content_limit: 100
|
|
||||||
order_by:
|
|
||||||
plausible:
|
plausible:
|
||||||
enable: true
|
enable: true
|
||||||
domain: lianglianglee.com
|
domain: lianglianglee.com
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hexo": "^6.3.0",
|
"hexo": "^6.3.0",
|
||||||
"hexo-abbrlink": "^2.2.1",
|
|
||||||
"hexo-bridge": "^1.2.0",
|
"hexo-bridge": "^1.2.0",
|
||||||
"hexo-filter-plantuml": "^2.1.1",
|
"hexo-filter-plantuml": "^2.1.1",
|
||||||
"hexo-generator-archive": "^2.0.0",
|
"hexo-generator-archive": "^2.0.0",
|
||||||
|
@ -262,11 +261,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.1.1"
|
"fill-range": "^7.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
|
@ -617,9 +615,8 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/ejs": {
|
"node_modules/ejs": {
|
||||||
"version": "3.1.10",
|
"version": "3.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
"license": "Apache-2.0",
|
||||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jake": "^10.8.5"
|
"jake": "^10.8.5"
|
||||||
},
|
},
|
||||||
|
@ -736,9 +733,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
},
|
},
|
||||||
|
@ -763,15 +759,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
|
||||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
},
|
},
|
||||||
|
@ -817,19 +812,6 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/fsevents": {
|
|
||||||
"version": "2.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
@ -945,51 +927,6 @@
|
||||||
"url": "https://opencollective.com/hexo"
|
"url": "https://opencollective.com/hexo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hexo-abbrlink": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/hexo-abbrlink/-/hexo-abbrlink-2.2.1.tgz",
|
|
||||||
"integrity": "sha512-yvazN7bbrIb7p8QU3nJ/8fbDmir1mFroYvUYcJz5xpc6DtszKggschmqZg6WNUdjhDBFyDwksrIUfwQnw0OOuA==",
|
|
||||||
"dependencies": {
|
|
||||||
"hexo-front-matter": "^1.0.0",
|
|
||||||
"hexo-fs": "^3.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hexo-abbrlink/node_modules/argparse": {
|
|
||||||
"version": "1.0.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
|
||||||
"dependencies": {
|
|
||||||
"sprintf-js": "~1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hexo-abbrlink/node_modules/hexo-front-matter": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/hexo-front-matter/-/hexo-front-matter-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-Hn8IIzgWWnxYTekrjnA0rxwWMoQHifyrxKMqVibmFaRKf4AQ2V6Xo13Jiso6CDwYfS+OdA41QS5DG1Y+QXA5gw==",
|
|
||||||
"dependencies": {
|
|
||||||
"js-yaml": "^3.13.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hexo-abbrlink/node_modules/js-yaml": {
|
|
||||||
"version": "3.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
|
||||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
|
||||||
"dependencies": {
|
|
||||||
"argparse": "^1.0.7",
|
|
||||||
"esprima": "^4.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"js-yaml": "bin/js-yaml.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/hexo-abbrlink/node_modules/sprintf-js": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
|
||||||
},
|
|
||||||
"node_modules/hexo-bridge": {
|
"node_modules/hexo-bridge": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/hexo-bridge/-/hexo-bridge-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/hexo-bridge/-/hexo-bridge-1.2.0.tgz",
|
||||||
|
@ -1527,8 +1464,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/is-number": {
|
"node_modules/is-number": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
|
@ -1818,9 +1754,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nunjucks": {
|
"node_modules/nunjucks": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
|
"license": "BSD-2-Clause",
|
||||||
"integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"a-sync-waterfall": "^1.0.0",
|
"a-sync-waterfall": "^1.0.0",
|
||||||
"asap": "^2.0.3",
|
"asap": "^2.0.3",
|
||||||
|
@ -2390,8 +2325,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
@ -2407,9 +2341,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tough-cookie": {
|
"node_modules/tough-cookie": {
|
||||||
"version": "4.1.4",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
|
"license": "BSD-3-Clause",
|
||||||
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"psl": "^1.1.33",
|
"psl": "^1.1.33",
|
||||||
"punycode": "^2.1.1",
|
"punycode": "^2.1.1",
|
||||||
|
@ -2571,9 +2504,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
@ -2583,9 +2515,8 @@
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.18.0",
|
"version": "8.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hexo": "^6.3.0",
|
"hexo": "^6.3.0",
|
||||||
"hexo-abbrlink": "^2.2.1",
|
|
||||||
"hexo-bridge": "^1.2.0",
|
"hexo-bridge": "^1.2.0",
|
||||||
"hexo-filter-plantuml": "^2.1.1",
|
"hexo-filter-plantuml": "^2.1.1",
|
||||||
"hexo-generator-archive": "^2.0.0",
|
"hexo-generator-archive": "^2.0.0",
|
||||||
|
|
|
@ -2,5 +2,4 @@
|
||||||
title: {{ title }}
|
title: {{ title }}
|
||||||
date: {{ date }}
|
date: {{ date }}
|
||||||
tags:
|
tags:
|
||||||
permalink: /posts/
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
---
|
|
||||||
title: 【发现好项目】给你的Postgres加个备份
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: fa974d33
|
|
||||||
date: 2024-07-29 23:03:04
|
|
||||||
---
|
|
||||||
|
|
||||||
GitHub地址:<https://github.com/eduardolat/pgbackweb>
|
|
||||||
|
|
||||||
# 项目简介
|
|
||||||
|
|
||||||
使用用户友好的 Web 界面轻松备份 PostgreSQL!
|
|
||||||
|
|
||||||
特点:
|
|
||||||
|
|
||||||
|
|
||||||
1. 界面友好简介
|
|
||||||
2. 备份上传到类S3存储
|
|
||||||
3. 支持定时备份
|
|
||||||
4. Web页面可直接下载备份
|
|
||||||
5. 敏感配置加密保存
|
|
||||||
|
|
||||||
缺点:
|
|
||||||
|
|
||||||
|
|
||||||
1. 不支持一键备份整个Server,多个数据库需要多次配置
|
|
||||||
2. 连接字符串没有拆分,导致配置时需要注意格式
|
|
||||||
|
|
||||||
# 部署
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
pgbackweb:
|
|
||||||
image: eduardolat/pgbackweb:latest
|
|
||||||
ports:
|
|
||||||
- "8085:8085" # Access the web interface at http://localhost:8085
|
|
||||||
environment:
|
|
||||||
PBW_ENCRYPTION_KEY: "my_secret_key"
|
|
||||||
PBW_POSTGRES_CONN_STRING: "postgresql://postgres:password@postgres:5432/pgbackweb?sslmode=disable"
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:16
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_DB: pgbackweb
|
|
||||||
POSTGRES_PASSWORD: password
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
volumes:
|
|
||||||
- ./data:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
```
|
|
||||||
|
|
||||||
替换掉环境变量:PBW_ENCRYPTION_KEY 为任意字符串
|
|
||||||
|
|
||||||
如果变更POSTGRES_PASSWORD,记得 PBW_POSTGRES_CONN_STRING 中的password也要变更
|
|
||||||
|
|
||||||
## 使用Minio作为备份后的存储
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: "3.7"
|
|
||||||
services:
|
|
||||||
minio:
|
|
||||||
image: quay.io/minio/minio:RELEASE.2024-01-01T16-36-33Z
|
|
||||||
ports:
|
|
||||||
- 9000:9000
|
|
||||||
- 9001:9001
|
|
||||||
volumes:
|
|
||||||
- ./minio/minio:/data
|
|
||||||
command: server --console-address ":9001" /data
|
|
||||||
environment:
|
|
||||||
- MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE // 请自行变更
|
|
||||||
- MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY //请自行变更
|
|
||||||
```
|
|
||||||
|
|
||||||
浏览器打开 ip:9001
|
|
||||||
|
|
||||||
输入MINIO_ROOT_USER,MINIO_ROOT_PASSWORD配置的账号密码
|
|
||||||
|
|
||||||
![Minio管理页](https://static.lianglianglee.com/2024/07/IM7MxgK.png)
|
|
||||||
|
|
||||||
Create a Bucket
|
|
||||||
|
|
||||||
![create a bucket](https://static.lianglianglee.com/2024/07/KCYMxgK.png)
|
|
||||||
|
|
||||||
创建完成后,minio即配置完成
|
|
||||||
|
|
||||||
# 使用
|
|
||||||
|
|
||||||
整个功能分为三大块
|
|
||||||
|
|
||||||
* Database 配置需要备份的数据库链接信息
|
|
||||||
* Destinations 配置S3存储,备份后的数据上传到该存储中
|
|
||||||
* Backups 备份的配置,什么时候备份,备份保存天数等
|
|
||||||
|
|
||||||
## 创建Database
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/07/WmcixgK.png)
|
|
||||||
|
|
||||||
Name可以自选,我习惯用用IP+数据库名称
|
|
||||||
|
|
||||||
Version支持Pg13-Pg16
|
|
||||||
|
|
||||||
Connection string:数据库的链接信息,格式为
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
postgresql://userName:password@hostname:5432/databaseName?sslmode=disable
|
|
||||||
```
|
|
||||||
|
|
||||||
比如
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
postgresql://postgres:password@postgres:5432/pgbackweb?sslmode=disable
|
|
||||||
```
|
|
||||||
|
|
||||||
测试后保存
|
|
||||||
|
|
||||||
## 创建Destination
|
|
||||||
|
|
||||||
这里使用类S3存储都可以,比如七牛云,阿里云的OSS,自建的Minio都可以。这里以Minio为例
|
|
||||||
|
|
||||||
![create destination](https://static.lianglianglee.com/2024/07/ASnmxgK.png)
|
|
||||||
|
|
||||||
Name可以自定义,我习惯用服务所在地+服务类型
|
|
||||||
|
|
||||||
Bucket Name 需要填写Minio中的Bucket
|
|
||||||
|
|
||||||
Endpoint 服务器的IP及端口,请注意这里要pgbackweb容器能访问的地址,端口使用9000,9001是管理的Web网页
|
|
||||||
|
|
||||||
Region 可随意填写
|
|
||||||
|
|
||||||
Access Key,Secret key 填写Minio的默认用户名密码即可。当然你也可以在MinioConsole再生成一个,这里不建议生成。
|
|
||||||
|
|
||||||
点击Test Connection 右下角跳出`Connection successful`代表配置没问题
|
|
||||||
|
|
||||||
## 配置Backup
|
|
||||||
|
|
||||||
![create backup](https://static.lianglianglee.com/2024/07/5XDnxgK.png)着重介绍几个选项
|
|
||||||
|
|
||||||
Database 选择已经创建的数据库连接
|
|
||||||
|
|
||||||
Destination 选择已创建的存储地址,多个Database可以用一个,用的Destnation directory区分即可
|
|
||||||
|
|
||||||
Cron是不带星期的格式,比如每天夜里2点 备份:`0 2 * * *`
|
|
||||||
|
|
||||||
Time zone是Cron表达式的时区,选自己所在的时区即可
|
|
||||||
|
|
||||||
Destnation directory是在S3中的文件夹,这里可以使用Database名称作为文件夹,更方便区分
|
|
||||||
|
|
||||||
Retention days 保留天数,自定义,当然也要看备份存储的成本
|
|
||||||
|
|
||||||
Options 无特殊要求默认即可
|
|
||||||
|
|
||||||
|
|
||||||
保存后,点击小闪电,即可立即执行备份
|
|
||||||
|
|
||||||
![backup list](https://static.lianglianglee.com/2024/07/BUROxgK.png)
|
|
||||||
|
|
||||||
## 查看备份情况
|
|
||||||
|
|
||||||
|
|
||||||
在Executions可以看到备份的执行状态。
|
|
||||||
|
|
||||||
![executions list](https://static.lianglianglee.com/2024/07/2bzOxgK.png)
|
|
||||||
|
|
||||||
进入Minio可以看到,文件夹名称就是在Backup中填写的文件夹
|
|
||||||
|
|
||||||
![minio list](https://static.lianglianglee.com/2024/07/Qz3oxgK.png)可以一层一层点进去看备份的文件,这里是tar压缩格式,可以下载后解压查看SQL文件
|
|
||||||
|
|
||||||
# 总结
|
|
||||||
|
|
||||||
pgbackweb是一个很简介,且入手难度极低的PostgreSQL备份工具,新手完全可以直接上手。基本满足了我的数据库备份需求。
|
|
|
@ -1,276 +0,0 @@
|
||||||
---
|
|
||||||
title: 使用R2+Page部署免费的图床【白嫖Cloudflare】
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: 22b7ecba
|
|
||||||
date: 2024-01-15 19:17:49
|
|
||||||
---
|
|
||||||
|
|
||||||
# 背景
|
|
||||||
|
|
||||||
作为一个程序员,一般写文章都是使用markdown编写,可以快速复制到其他平台上。然而markdown有一个严重的问题,就是图片保存的问题。
|
|
||||||
|
|
||||||
刚开始我使用的typora作为编辑器,图片保存在md文件同目录的assets文件夹。一直以来都是自己阅读,后来有了在线阅读的需求,就自己编写了一个markdown阅读工具,完全根据自己的习惯编写。
|
|
||||||
|
|
||||||
后来做了博客,面临复制到博客的需求,每次编辑完,再复制图片到博客的文件夹,整个流程就繁琐了。故想一统markdown的图片存储。
|
|
||||||
|
|
||||||
现在的策略是使用picgo上传到R2上,然而这个工具有一个严重的问题,多客户端同步的问题。使用一段时间就不再使用了。
|
|
||||||
|
|
||||||
一直在想,能不能做一个网页版的图床,使用网页上传,最好不做元数据存储,直接读取R2的目录。
|
|
||||||
|
|
||||||
# 调研
|
|
||||||
|
|
||||||
程序员,就要自己**找**轮子,github上搜搜一番,找到一个还不错的工具https://github.com/roimdev/roim-picx
|
|
||||||
|
|
||||||
已经实现了这些功能,对我来说足够了
|
|
||||||
|
|
||||||
> * 图片批量上传
|
|
||||||
> * 图片列表查询
|
|
||||||
> * 图片删除
|
|
||||||
> * 目录创建
|
|
||||||
> * 按目录查询
|
|
||||||
> * 链接地址点击复制
|
|
||||||
> * 简单的身份认证功能,进入管理页面需要授权
|
|
||||||
|
|
||||||
部署上去试了试,整体对我来说很适合。其文档写的也不是很完善,就简单记录一下。
|
|
||||||
|
|
||||||
# 部署
|
|
||||||
|
|
||||||
该项目使用了Cloudflare的三个能力
|
|
||||||
|
|
||||||
|
|
||||||
1. **KV**:Token存储
|
|
||||||
2. **R2**:图片存储
|
|
||||||
3. **Page**:提供页面访问
|
|
||||||
|
|
||||||
Page中使用了functions作为后端服务
|
|
||||||
|
|
||||||
## 准备工作
|
|
||||||
|
|
||||||
**创建KV存储**
|
|
||||||
|
|
||||||
登录Cloudflare账号,`首页/Workers和Pages/KV`
|
|
||||||
|
|
||||||
创建一个命名空间
|
|
||||||
|
|
||||||
**创建R2存储**
|
|
||||||
|
|
||||||
进入`首页/R2`
|
|
||||||
|
|
||||||
创建存储桶。位置可自动
|
|
||||||
|
|
||||||
## fork仓库
|
|
||||||
|
|
||||||
略
|
|
||||||
|
|
||||||
## 部署
|
|
||||||
|
|
||||||
可按照教程部署
|
|
||||||
|
|
||||||
## 配置
|
|
||||||
|
|
||||||
因为其使用了KV和R2存储,则需要在`page详情/设置/函数`中配置这两个变量\nKV命名绑定,变量名称`XK`,KV空间选刚才创建的
|
|
||||||
|
|
||||||
R2 存储桶绑定,变量名称`PICX`,R2存储通选刚刚创建的
|
|
||||||
|
|
||||||
还需要配置一个环境变量`page详情/设置/环境变量`
|
|
||||||
|
|
||||||
新增`BASE_URL`,值空着不填即可
|
|
||||||
|
|
||||||
**Token配置**
|
|
||||||
|
|
||||||
其token是从KV存储中读取的,所以需要进入KV存储
|
|
||||||
|
|
||||||
添加条目\n密钥:`PICX_AUTH_TOKEN`,值可以自定义
|
|
||||||
|
|
||||||
|
|
||||||
**访问:**
|
|
||||||
|
|
||||||
![image.png](https://static.lianglianglee.com/2024/01/CkUQ8aK.png)
|
|
||||||
|
|
||||||
打开后,输入`PICX_AUTH_TOKEN`定义的值即可
|
|
||||||
|
|
||||||
# 魔改
|
|
||||||
|
|
||||||
作为一个开源项目,肯定不会100%适合我,根据我的需求,做了一点点的改动。
|
|
||||||
|
|
||||||
|
|
||||||
1. 调整文件上传的存放路径为`年/月/文件`
|
|
||||||
2. 页面复制的URL为额外的域名+文件地址
|
|
||||||
3. KV只用来方Token太浪费,Token更改为环境变量存储
|
|
||||||
4. 修改网站的标题,Logo等
|
|
||||||
|
|
||||||
|
|
||||||
## 调整文件上传路径
|
|
||||||
|
|
||||||
原来的文件上传后,会传到根路径中,作为临时图床可以,如果作为静态图片存储,就不合适了,图片多了没办法处理
|
|
||||||
|
|
||||||
文件名称生成在`functions\rest\utils.ts`
|
|
||||||
|
|
||||||
修改`getFileName`为`getFilePath`,并做以下改动:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 获取文件名
|
|
||||||
export async function getFilePath(val: string, time: number): Promise<string> {
|
|
||||||
const types = supportFiles.filter(it => it.type === val)
|
|
||||||
if (!types || types.length < 1) {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
const rand = Math.floor(Math.random() * 100000)
|
|
||||||
const fileName = randomString(time + rand).concat(`.${types[0].ext}`)
|
|
||||||
let date = new Date()
|
|
||||||
const year = date.getFullYear() //获取完整的年份(4位)
|
|
||||||
let month = date.getMonth() + 1 //获取当前月份(0-11,0代表1月)
|
|
||||||
if (month < 10) {
|
|
||||||
month = `0${month}`;
|
|
||||||
}
|
|
||||||
return `${year}/${month}/${fileName}`
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
修改调用方:
|
|
||||||
|
|
||||||
全局搜索`getFileName`,替换成`getFilePath`
|
|
||||||
|
|
||||||
部署后,测试上传是否有问题
|
|
||||||
|
|
||||||
## 增加复制地址
|
|
||||||
|
|
||||||
想法如下:
|
|
||||||
|
|
||||||
原有的图片地址不变的情况下,图片属性增加一个copyUrl的属性,在列表,上传后返回该属性,域名配置使用环境变量
|
|
||||||
|
|
||||||
**环境变更**
|
|
||||||
|
|
||||||
`functions\rest\[[path]].ts`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export interface Env {
|
|
||||||
BASE_URL: string
|
|
||||||
COPY_URL: string //新增
|
|
||||||
XK: KVNamespace
|
|
||||||
PICX: R2Bucket
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
在cloudflard的设置,增加变量
|
|
||||||
|
|
||||||
**图片对象**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export interface ImgItem {
|
|
||||||
key : string
|
|
||||||
url : string
|
|
||||||
size: number
|
|
||||||
copyUrl: string
|
|
||||||
filename ?: string
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**API返回**
|
|
||||||
|
|
||||||
`functions\rest\routes\index.ts`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// list接口
|
|
||||||
return <ImgItem>{
|
|
||||||
url: `/rest/${it.key}`,
|
|
||||||
copyUrl: `${env.COPY_URL}/${it.key}`,
|
|
||||||
key: it.key,
|
|
||||||
size: it.size
|
|
||||||
}
|
|
||||||
// 上传接口
|
|
||||||
urls.push({
|
|
||||||
key: object.key,
|
|
||||||
size: object.size,
|
|
||||||
copyUrl: `${env.COPY_URL}/${object.key}`,
|
|
||||||
url: `/rest/${object.key}`,
|
|
||||||
filename: item.name
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
**列表页面**
|
|
||||||
|
|
||||||
|
|
||||||
1. 传递参数
|
|
||||||
|
|
||||||
`src\views\ManageImages.vue`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// image-box 增加copyUrl传递
|
|
||||||
|
|
||||||
<image-box
|
|
||||||
:src="item.url"
|
|
||||||
:copyUrl="item.copyUrl"
|
|
||||||
:name="item.key"
|
|
||||||
:size="item.size"
|
|
||||||
@delete="deleteImage(item.key)"
|
|
||||||
mode="uploaded"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
2. 接受入参
|
|
||||||
|
|
||||||
`src\components\ImageBox.vue`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 接受入参
|
|
||||||
const props = defineProps<{
|
|
||||||
src: string
|
|
||||||
copyUrl:string // 新增
|
|
||||||
name: string
|
|
||||||
size: number
|
|
||||||
mode: 'converted' | 'uploaded'
|
|
||||||
uploadedAt?: number
|
|
||||||
expiresAt?: number
|
|
||||||
}>()
|
|
||||||
|
|
||||||
---
|
|
||||||
//copyLink 方法入参修改为:copyUrl
|
|
||||||
@click="copyLink(copyUrl)"
|
|
||||||
```
|
|
||||||
|
|
||||||
**上传页面**
|
|
||||||
|
|
||||||
`src\components\ImageItem.vue`
|
|
||||||
|
|
||||||
将`htmlLink`,`markdownLink`,`LINK`这三个地方的url改成`copyUrl`
|
|
||||||
|
|
||||||
|
|
||||||
## Token使用环境变量存储
|
|
||||||
|
|
||||||
环境变量在`functions\rest\[[path]].ts`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export interface Env {
|
|
||||||
AUTH_TOKEN: string
|
|
||||||
COPY_URL: string
|
|
||||||
R2: R2Bucket
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
调用方修改`functions\rest\routes\index.ts`
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
await env.XK.get('PICX_AUTH_TOKEN')
|
|
||||||
// 修改为:
|
|
||||||
env.AUTH_TOKEN;
|
|
||||||
```
|
|
||||||
|
|
||||||
新增环境变量:`AUTH_TOKEN`
|
|
||||||
|
|
||||||
环境变量修改完成后,记得重新部署
|
|
||||||
|
|
||||||
## 修改网站标题
|
|
||||||
|
|
||||||
网站首页在`src\App.vue`
|
|
||||||
|
|
||||||
直接修改部署即可。
|
|
||||||
|
|
||||||
|
|
||||||
# 其他
|
|
||||||
|
|
||||||
魔改后的代码地址:<https://github.com/liangliangle/roim-picx>
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: Debian创建Raid5阵列
|
title: Debian创建Raid5阵列
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 77c1eb7c
|
|
||||||
date: 2023-06-29 01:12:23
|
date: 2023-06-29 01:12:23
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 使用Docker部署Java程序
|
title: 使用Docker部署Java程序
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: a1073832
|
|
||||||
date: 2023-05-17 21:59:19
|
date: 2023-05-17 21:59:19
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: Docker部署Seafile服务
|
title: Docker部署Seafile服务
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 1f9eb31a
|
|
||||||
date: 2023-07-04 19:58:00
|
date: 2023-07-04 19:58:00
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
---
|
|
||||||
title: 记一次Dubbo invoke命令的问题
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: 851d3eeb
|
|
||||||
date: 2024-03-14 11:04:12
|
|
||||||
---
|
|
||||||
# 记一次Dubbo invoke命令的问题
|
|
||||||
|
|
||||||
# 背景
|
|
||||||
|
|
||||||
因为线上发生了一次死锁问题,导致数据没有正常写入,需要手动调用dubbo invoke重试。
|
|
||||||
|
|
||||||
接口入参为 String, String, Object
|
|
||||||
|
|
||||||
命令为:
|
|
||||||
|
|
||||||
```java
|
|
||||||
invoke xxService.xxMethod("123","321",{...})
|
|
||||||
```
|
|
||||||
|
|
||||||
愉快进入容器,开始执行,不出意外,意外就发生了
|
|
||||||
|
|
||||||
```java
|
|
||||||
Invalid json argument, cause: unclosed string :
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# 排查
|
|
||||||
|
|
||||||
最开始以为是JSON格式有问题,开始排查格式,用了各种校验工具都没有发现问题
|
|
||||||
|
|
||||||
举例格式如下:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"class": "xxx",
|
|
||||||
"xx": "xxx",
|
|
||||||
"xxx": "xxx",
|
|
||||||
"xxxx": "xxx",
|
|
||||||
"xxx": "xxxx",
|
|
||||||
"xxxRequest": {
|
|
||||||
"xxxNo": "xxx",
|
|
||||||
"xxxName": "xx(XXX)x"
|
|
||||||
},
|
|
||||||
"xxxItemDataList": [
|
|
||||||
{
|
|
||||||
"xxx": "xxx",
|
|
||||||
"xxx": "xxx",
|
|
||||||
"class": "xxx.xxx.xxx.xxx"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
因为接口的入参是一个父类,所以用class执行具体子类类型,
|
|
||||||
|
|
||||||
list中同样也制定了类型
|
|
||||||
|
|
||||||
用了各种工具校验,JSON都没有问题,最后跟代码发现,**是因为Json中的value有英文的括号,导致命令解析出现了问题,到括号就结束了解析**,实际到Dubbo中的JSON是
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"class": "xxx",
|
|
||||||
"xx": "xxx",
|
|
||||||
"xxx": "xxx",
|
|
||||||
"xxxx": "xxx",
|
|
||||||
"xxx": "xxxx",
|
|
||||||
"xxxRequest": {
|
|
||||||
"xxxNo": "xxx",
|
|
||||||
"xxxName": "xx(XXX
|
|
||||||
```
|
|
||||||
|
|
||||||
这可不就是JSON格式有误吗?
|
|
||||||
|
|
||||||
# 代码解析
|
|
||||||
|
|
||||||
dubbo分支切换到2.7.x
|
|
||||||
|
|
||||||
全局搜`Invalid json argument`,找到代码
|
|
||||||
|
|
||||||
![clipboard.png](https://static.lianglianglee.com/2024/03/Y018tCK.png)
|
|
||||||
|
|
||||||
按照第一个英文括号解析的,导致整个命令被强制截断。
|
|
||||||
|
|
||||||
再看一下最新代码 3.2的版本
|
|
||||||
|
|
||||||
![clipboard.png](https://static.lianglianglee.com/2024/03/3k3JtCK.png)
|
|
||||||
|
|
||||||
最新版已经修复了这个问题。
|
|
||||||
|
|
||||||
|
|
||||||
# 总结
|
|
||||||
|
|
||||||
当dubbo版本是2.7.x,使用invoke时,参数中不能有英文右括号
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 记一次业务系统与ES的同步方案升级
|
title: 记一次业务系统与ES的同步方案升级
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: cbda41f1
|
|
||||||
date: 2023-08-28 15:05:47
|
date: 2023-08-28 15:05:47
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 从文件看Git
|
title: 从文件看Git
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: e25aabb4
|
|
||||||
date: 2023-10-26 11:15:09
|
date: 2023-10-26 11:15:09
|
||||||
---
|
---
|
||||||
# 从文件看Git
|
# 从文件看Git
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
---
|
|
||||||
title: 全球访问加速调研
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: d1ec7f99
|
|
||||||
date: 2024-06-12 22:51:13
|
|
||||||
---
|
|
||||||
# **背景**
|
|
||||||
|
|
||||||
公司的所有业务系统都部署在上海地区,北美地区访问延迟不稳定。
|
|
||||||
|
|
||||||
以下为某服务的API接口主要业务地区的初次访问
|
|
||||||
|
|
||||||
接口:`https://xxxx.com/health/check`
|
|
||||||
|
|
||||||
| **地区** | **建连时间** | **首包时间** | **总耗时** |
|
|
||||||
| ---------- | ------------ | ------------ | ---------- |
|
|
||||||
| 加利福尼亚 | 160ms | 165ms | 1063ms |
|
|
||||||
| 弗吉尼亚 | 207ms | 220ms | 842ms |
|
|
||||||
| 新加坡 | 68ms | 74ms | 332ms |
|
|
||||||
| 上海 | 6ms | 19ms | 37ms |
|
|
||||||
| 深圳 | 34ms | 44ms | 303ms |
|
|
||||||
|
|
||||||
> 数据来源:<https://boce.aliyun.com/detect/http>
|
|
||||||
|
|
||||||
除了以上耗时,还有
|
|
||||||
|
|
||||||
1. DNS解析耗时
|
|
||||||
2. SSL握手耗时
|
|
||||||
3. 下载耗时
|
|
||||||
|
|
||||||
可以看到 北美访问基本耗时在1秒以上,如果稳定的1秒钟的延迟,问题也不算特别大,然而延迟是不稳定的,比如
|
|
||||||
|
|
||||||
![加利福尼亚-夜间延迟数据](https://static.lianglianglee.com/2024/06/Z1WIKFK.png)
|
|
||||||
|
|
||||||
![弗吉尼亚-夜间延迟数据](https://static.lianglianglee.com/2024/06/cJyIKFK.png)
|
|
||||||
|
|
||||||
数据来源:阿里云监控-定时拨测 晚上9点-第二天9点的响应时间
|
|
||||||
|
|
||||||
在高峰期可以看到在晚上9点后,延迟就开始不稳定了,美西延迟波动还不算大,美东直接变为不可用了。
|
|
||||||
|
|
||||||
# 为什么会慢
|
|
||||||
|
|
||||||
说到那么慢,就需要先了解跨国流量是怎么走的[海缆地图](https://www.submarinecablemap.com/)
|
|
||||||
|
|
||||||
## 登录站
|
|
||||||
|
|
||||||
目前中国的登录站主要有以下几个地方
|
|
||||||
|
|
||||||
- [青岛](https://www.submarinecablemap.com/landing-point/qingdao-china)
|
|
||||||
- 上海
|
|
||||||
- [崇明](https://www.submarinecablemap.com/landing-point/chongming-china)
|
|
||||||
- [临港](https://www.submarinecablemap.com/landing-point/lingang-china)
|
|
||||||
- [南汇](https://www.submarinecablemap.com/landing-point/nanhui-china)
|
|
||||||
- [福州](https://www.submarinecablemap.com/landing-point/fuzhou-china)
|
|
||||||
- [汕头](https://www.submarinecablemap.com/landing-point/shantou-china)
|
|
||||||
- [北海](https://www.submarinecablemap.com/landing-point/beihai-china)
|
|
||||||
- [海南](https://www.submarinecablemap.com/landing-point/hainan-china)
|
|
||||||
- [文昌](https://www.submarinecablemap.com/landing-point/wenchang-china)
|
|
||||||
- [陵水](https://www.submarinecablemap.com/landing-point/lingshui-china)
|
|
||||||
|
|
||||||
## 走向分布
|
|
||||||
|
|
||||||
中美直连的线路目前只有两条
|
|
||||||
|
|
||||||
- [TPE](https://www.submarinecablemap.com/submarine-cable/trans-pacific-express-tpe-cable-system)(跨太平洋快线)
|
|
||||||
- [NCP](https://www.submarinecablemap.com/submarine-cable/new-cross-pacific-ncp-cable-system)(新跨太平洋海缆)
|
|
||||||
|
|
||||||
往东亚方向的的
|
|
||||||
|
|
||||||
- [APCN-2](https://www.submarinecablemap.com/submarine-cable/apcn-2)(亚太2号海底光缆)
|
|
||||||
- [APG](https://www.submarinecablemap.com/submarine-cable/asia-pacific-gateway-apg)(亚太直达国际海底光缆)
|
|
||||||
- [EAC-C2C](https://www.submarinecablemap.com/submarine-cable/eac-c2c)(东亚海底光缆)
|
|
||||||
- [SJC](https://www.submarinecablemap.com/submarine-cable/southeast-asia-japan-cable-sjc)(东南亚日本海底光缆)
|
|
||||||
- [ADC](https://www.submarinecablemap.com/submarine-cable/asia-direct-cable-adc)(亚洲直线)2024年Q4投入使用
|
|
||||||
- [SJC-2](https://www.submarinecablemap.com/submarine-cable/southeast-asia-japan-cable-2-sjc2)(东南亚-日本2号海底光缆)2025年Q1投入使用
|
|
||||||
|
|
||||||
往欧洲方向
|
|
||||||
|
|
||||||
- [SEA-ME-WE-3](https://www.submarinecablemap.com/submarine-cable/seamewe-3)(亚欧3号海底光缆)
|
|
||||||
- [SEA-ME-WE-4](https://www.submarinecablemap.com/submarine-cable/seamewe-4)(亚欧4号海底光缆)
|
|
||||||
- [FEA](https://www.submarinecablemap.com/submarine-cable/flag-europe-asia-fea)(环球海底光缆)
|
|
||||||
|
|
||||||
往台湾方向
|
|
||||||
|
|
||||||
- [TSE-1](https://www.submarinecablemap.com/submarine-cable/taiwan-strait-express-1-tse-1)(海峡光缆1号)
|
|
||||||
|
|
||||||
## **为什么中国的跨国海底光缆那么少?**
|
|
||||||
|
|
||||||
因为跨国海底光缆不是一个国家的能建成的,有登陆站的国家都要参与建设,所以要**一拍即合**
|
|
||||||
|
|
||||||
拿跨太平洋快线举例,参与的企业有【AT&T,中国电信,中华电信,KT,NTT, Verizon】登陆站有6个【上海-崇明,山东-青岛,日本-东京,韩国-巨济,台湾-炭水,美国-俄勒冈】
|
|
||||||
|
|
||||||
![clipboard.png](https://static.lianglianglee.com/2024/06/iiIoKFK.png)
|
|
||||||
|
|
||||||
所以协同建造难。
|
|
||||||
|
|
||||||
晚间访问高峰时,公共线路丢包,拥堵情况严重,延迟爆炸
|
|
||||||
|
|
||||||
当然建造成本那么高,肯定要想办法盈利,故各运营方提供了付费的国际精品专线
|
|
||||||
|
|
||||||
# 加速访问
|
|
||||||
|
|
||||||
**以美国访问中国为例**
|
|
||||||
|
|
||||||
在美中之间,有两个使用高品质线路互联的服务器,两个服务器之间不存在阻塞,丢包情况。那就可以借助这两个服务器做一些改造。
|
|
||||||
|
|
||||||
美国用户访问美国的这个服务器,由这个服务器把流量打到中国的这个服务器上,再由中国的服务器向源服务器发起请求,再把响应返回出去。那就形成3段稳定的链路
|
|
||||||
|
|
||||||
![clipboard.png](https://static.lianglianglee.com/2024/06/QcNUKFK.png)
|
|
||||||
|
|
||||||
高品跨国链路,一般企业不会采购,所以购买现成的是最佳选择,阿里云就提供这样的服务
|
|
||||||
|
|
||||||
## 不能解决什么?
|
|
||||||
|
|
||||||
全球加速不能解决传输时延问题。
|
|
||||||
|
|
||||||
比如中国到美西的访问,传输时延在150毫秒左右。
|
|
||||||
|
|
||||||
## **阿里云全球加速**
|
|
||||||
|
|
||||||
![阿里云全球加速](https://static.lianglianglee.com/2024/06/XvfiKFK.png)
|
|
||||||
|
|
||||||
以中美间访问为例,无论是中国访问美国,还是美国访问中国,流量都是走**公共链路**。高峰期网络拥堵,丢包率、延迟都不可控且不稳定。
|
|
||||||
|
|
||||||
全球加速是中美间的流量**不走公共链路**,而是走阿里云的全球网络。基本不会产生拥堵,丢包情况,延迟可控且稳定。
|
|
||||||
|
|
||||||
## 加速方式
|
|
||||||
|
|
||||||
全球加速有三种接入方式,每种方式有不同的实现方式
|
|
||||||
|
|
||||||
1. 弹性公网IP
|
|
||||||
2. 任播弹性公网IP
|
|
||||||
3. CNAME
|
|
||||||
|
|
||||||
### 弹性公网IP
|
|
||||||
|
|
||||||
弹性公网IP,简单来说就是每个地区提供单独的公网IP,对应地区连接各自地区的IP
|
|
||||||
|
|
||||||
### 任播弹性公网IP
|
|
||||||
|
|
||||||
弹性公网IP有一个问题,每个地区都有对应的IP,没办法一个IP访问全部,如果连接到错误地区的IP,延迟更高。
|
|
||||||
|
|
||||||
这个时候借助任播技术,就可以实现一个IP指定地区的访问。
|
|
||||||
|
|
||||||
> **[任播](https://zh.wikipedia.org/wiki/%E4%BB%BB%E6%92%AD)**(英语:**anycast**)是一种网络寻址和路由的策略,使得资料可以根据路由拓扑来决定送到"最近"或"最好"的目的地。
|
|
||||||
|
|
||||||
### CNAME
|
|
||||||
|
|
||||||
CNAME实际上是套了一层的DNS解析,在阿里云的全球加速中,最后解析到的IP依旧是一个任播公网IP
|
|
||||||
|
|
||||||
# **切换流程**
|
|
||||||
|
|
||||||
DNS切换会影响全部用户,切换流程如下:
|
|
||||||
|
|
||||||
## **验证期**
|
|
||||||
|
|
||||||
- 切换CNAME解析到全球加速的域名
|
|
||||||
- TTL设置为1分钟(能选择的最短时间即可)
|
|
||||||
|
|
||||||
## **验证**
|
|
||||||
|
|
||||||
1. 清空本地DNS缓存
|
|
||||||
2. 使用dig命令解析域名
|
|
||||||
1. dig xxxx.com
|
|
||||||
3. 本地访问`https://xxxx.com/health/check`
|
|
||||||
4. 使用加速地区的ECS或VPS等,访问 `https://xxxx.com/health/check`
|
|
||||||
|
|
||||||
## **验证完成**
|
|
||||||
|
|
||||||
- 修改TTL恢复原本时长
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
## **回滚**
|
|
||||||
|
|
||||||
CNAME解析切换回原来的即可
|
|
||||||
|
|
||||||
> 切换时间视TTL不同,有所不同,一般会略高于TTL时间
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
title: 使用Hexo+cloudflare搭建个人博客[当前博客搭建过程]
|
||||||
title: '使用Hexo+cloudflare搭建个人博客[当前博客搭建过程]'
|
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: d3175a9a
|
|
||||||
date: 2023-04-05 14:38:18
|
date: 2023-04-05 14:38:18
|
||||||
---
|
---
|
||||||
# 1 背景介绍
|
# 1 背景介绍
|
||||||
|
|
|
@ -1,410 +0,0 @@
|
||||||
---
|
|
||||||
title: 制作CA签发验证SSL证书
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
date: '2024-01-12T17:05:48.000Z'
|
|
||||||
abbrlink: 54c1e4fe
|
|
||||||
---
|
|
||||||
# 背景
|
|
||||||
|
|
||||||
**为什么要用SSL?**
|
|
||||||
|
|
||||||
对于我来说,最重要的就是**数据加密**。在互联网访问中,HTTPS相比HTTP,提供了TLS加密数据。别人只能看到你访问了某个域名和IP,但是不知道我们之间传输了什么内容。
|
|
||||||
|
|
||||||
**TLS解决了什么?**
|
|
||||||
|
|
||||||
|
|
||||||
1. 如何保证数据传输的保密性;
|
|
||||||
2. 如何保证数据传输的完整性;
|
|
||||||
3. 如何保证通信主体的真实性;
|
|
||||||
|
|
||||||
其一,它用对称加密方法加密中间来回传输的流量,使得中间节点只能看到密文,并且中间节点一般拿不到解密密钥把密文恢复成明文。
|
|
||||||
|
|
||||||
其二,它提供了端到端的安全性,就好像是在两个进程之间建立了一条坚实可靠的「管道」保护着管道里边传输的报文,使得数据在进程到进程之间的传播是完整的,就算被篡改了也是能检验得出的;
|
|
||||||
|
|
||||||
其三,它通过公钥加密的技术,结合现有的 PKI(公钥密码学基础设施),提供了通信双方验证对端身份真实性的一种机制,
|
|
||||||
|
|
||||||
**为什么不用免费的SSL证书?**
|
|
||||||
|
|
||||||
实际上我用了Cloudflare的服务后,自动提供了SSL的证书,且不需要关心有效期的问题。
|
|
||||||
|
|
||||||
但是 [在公司无感访问家里的服务](https://blog.lianglianglee.com/2024/01/11/office_visit_home_server/) 中,办公环境下,全程都是HTTP,数据完全透明,同样需要HTTPS为数据安全提供保障。
|
|
||||||
|
|
||||||
如果使用免费的证书,则每三个月需要申请一次,比较麻烦,因为都是内网访问,所以更简单一点,直接用自己的根证书,后续也能用于内网的各种HTTPS访问
|
|
||||||
|
|
||||||
**计算机怎么知道这个证书是可信的呢?**
|
|
||||||
|
|
||||||
操作系统通常会预装一组根证书(Root Certificates)作为信任锚点,用于验证数字证书的真实性。这些根证书是由大型、受信任的CA签发的,因此用户可以信任这些根证书,从而信任由这些根证书签发的其他数字证书。这种信任链建立了对整个公共PKI的信任,确保了数字证书的可信度。新的根证书可能会在操作系统更新中加入,以适应不断变化的证书颁发机构和安全需求。
|
|
||||||
|
|
||||||
**获取TSL的流程**
|
|
||||||
|
|
||||||
获取TLS(Transport Layer Security)证书通常涉及以下步骤。因为TLS的前身是SSL(Secure Sockets Layer),所以经常会说SSL证书
|
|
||||||
|
|
||||||
|
|
||||||
1. 选择证书颁发机构
|
|
||||||
2. 生成证书签发请求(CSR)
|
|
||||||
3. 提交CSR到CA
|
|
||||||
4. 身份验证
|
|
||||||
5. 接受证书
|
|
||||||
6. 安装证书
|
|
||||||
|
|
||||||
主要流程如上,实际过程中,提交CSR,身份验证,接受证书都会受CA机构的影响,会有所不同。
|
|
||||||
|
|
||||||
# 创建根证书
|
|
||||||
|
|
||||||
根据前面的介绍,我们只需要安装自己生成的根证书,那这个证书颁发的所有证书都是可信的。所以我们需要先生成一个根证书,然后让私有设备信任这个根证书。
|
|
||||||
|
|
||||||
> 对于这篇文章中讲到的根证书、普通证书,学名都是 X.509v3 证书,区别只在于:
|
|
||||||
>
|
|
||||||
>
|
|
||||||
> 1. 根证书是自己给自己签发的
|
|
||||||
> 2. 根证书和普通证书的扩展参数有些不一样
|
|
||||||
>
|
|
||||||
> \
|
|
||||||
> CA 证书也好普通证书也好,都可以统一地用 openssl 的那一套命令行工具来生成、签发、验证和查看,非常的方便。
|
|
||||||
|
|
||||||
接下来不涉及到 CRL 和 OCSP,感兴趣的朋友可以自行查阅 Wikipedia 和 [rfc5280](https://datatracker.ietf.org/doc/html/rfc5280).
|
|
||||||
|
|
||||||
## 生成私钥
|
|
||||||
|
|
||||||
最好在一个单独的目录操作,先生成一个CA私钥
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl genrsa -out ca.key 2048
|
|
||||||
```
|
|
||||||
|
|
||||||
我们会得到一个 [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) 格式的私钥,它的默认 permissions 也很有意思:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ls -all ca.key
|
|
||||||
---
|
|
||||||
-rw------- 1 root root 1704 Dec 10 15:18 ca.key
|
|
||||||
```
|
|
||||||
|
|
||||||
接下来要开始签发自签证书,按照 openssl 的惯例,我们可以先把证书的一些信息写到一个配置文件中:包括这个证书对应的主体 (subject) 是谁、这个证书是做什么用的、这个证书的唯一标识和签发者的唯一标识等获取方式等:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[ req ]
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
prompt = no
|
|
||||||
x509_extensions = v3_ca
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = CN
|
|
||||||
stateOrProvinceName = Beijing
|
|
||||||
localityName = Beijing
|
|
||||||
0.organizationName = LocalOrganizationName
|
|
||||||
organizationalUnitName = IT
|
|
||||||
commonName = Homelab Root CA
|
|
||||||
emailAddress = admin@example.com
|
|
||||||
|
|
||||||
[ v3_ca ]
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always,issuer
|
|
||||||
basicConstraints = critical, CA:true, pathlen:2
|
|
||||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
||||||
```
|
|
||||||
|
|
||||||
把它保存为当前目录的 `ca.root.ini` 文件。
|
|
||||||
|
|
||||||
> 希望进一步了解配置文件的格式以及其中各个字段含义的读者可以参阅 man 5 config 和 man 5 x509v3_config.
|
|
||||||
|
|
||||||
## 生成证书
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl req -new -x509 -key ca.key -config ca.root.ini -out ca.crt
|
|
||||||
```
|
|
||||||
|
|
||||||
得到一个 PEM 格式的 `ca.crt` 文件位于当前文件夹。
|
|
||||||
|
|
||||||
我们可以通过 `openssl x509` 命令查看此证书的详细信息:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl x509 -in ca.crt -noout -text
|
|
||||||
---
|
|
||||||
Certificate:
|
|
||||||
Data:
|
|
||||||
Version: 3 (0x2)
|
|
||||||
Serial Number:
|
|
||||||
60:9a:7a:ba:8c:98:9b:f8:1a:de:46:c4:0c:05:0c:7f:b2:b8:c9:ab
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Issuer: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com
|
|
||||||
Validity
|
|
||||||
Not Before: Jan 12 09:31:08 2024 GMT
|
|
||||||
Not After : Feb 11 09:31:08 2024 GMT
|
|
||||||
Subject: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com
|
|
||||||
Subject Public Key Info:
|
|
||||||
Public Key Algorithm: rsaEncryption
|
|
||||||
Public-Key: (2048 bit)
|
|
||||||
Modulus:
|
|
||||||
00:bf:c3:ee:37:75:2d:15:9c:1a:dd:d7:77:5c:78:
|
|
||||||
.....略
|
|
||||||
dd:a7:5e:09:36:d4:87:96:0b:42:12:a3:fd:99:95:
|
|
||||||
8c:63
|
|
||||||
Exponent: 65537 (0x10001)
|
|
||||||
X509v3 extensions:
|
|
||||||
X509v3 Subject Key Identifier:
|
|
||||||
51:27:75:BE:3E:24:AE:A5:93:C7:1C:DE:F8:23:FB:7F:4D:BF:53:34
|
|
||||||
X509v3 Authority Key Identifier:
|
|
||||||
51:27:75:BE:3E:24:AE:A5:93:C7:1C:DE:F8:23:FB:7F:4D:BF:53:34
|
|
||||||
X509v3 Basic Constraints: critical
|
|
||||||
CA:TRUE, pathlen:2
|
|
||||||
X509v3 Key Usage: critical
|
|
||||||
Digital Signature, Certificate Sign, CRL Sign
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Signature Value:
|
|
||||||
8a:c9:ab:63:2d:a2:aa:72:7b:d9:41:27:d2:5d:00:14:f0:77:
|
|
||||||
...略
|
|
||||||
76:08:94:3c:b5:24:12:0a:71:8a:46:60:5e:83:78:1d:09:68:
|
|
||||||
f3:80:87:0e
|
|
||||||
```
|
|
||||||
|
|
||||||
我们发现 X509v3 Subject Key Identifier 和 X509v3 Authority Key Identifier 有相同的值,前者是它自己的唯一编号,后者是签发此证书的证书的唯一编号,再结合 X509v3 Basic Constraints 的 CA:TRUE 字样,使得验证者可以判断它是一个自签的根 CA 证书。
|
|
||||||
|
|
||||||
这个 CA 证书的 pathlen 是 2,这意味着它还可以再签发一个 pathlen 等于 1 的中级 CA 证书,然后这个 pathlen 等于 1 的中级 CA 证书自己又可以再签发一个 pathlen 等于 0 的中级 CA 证书,pathlen 等于 0 的 CA 证书不能再签发 CA 证书,只能签发最终用户证书 (end-entity certificate).
|
|
||||||
|
|
||||||
我们可以用这行命令验证它:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl verify --show_chain -CAfile ca.crt ca.crt
|
|
||||||
---
|
|
||||||
ca.crt: OK
|
|
||||||
Chain:
|
|
||||||
depth=0: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
接下来我们选择直接用它签发 end-entity certificate
|
|
||||||
|
|
||||||
# 证书签发
|
|
||||||
|
|
||||||
## 生成私钥
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl genrsa -out x.com.key 2048
|
|
||||||
```
|
|
||||||
|
|
||||||
准备一个 `x.com.ini` 配置文件,填写主体信息:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[ req ]
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
prompt = no
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = CN
|
|
||||||
stateOrProvinceName = Beijing
|
|
||||||
localityName = Beijing
|
|
||||||
0.organizationName = LocalOrganizationName
|
|
||||||
organizationalUnitName = IT
|
|
||||||
commonName = Homelab Root CA
|
|
||||||
emailAddress = admin@example.com
|
|
||||||
|
|
||||||
subjectAltName=@SubjectAlternativeName
|
|
||||||
|
|
||||||
[ SubjectAlternativeName ]
|
|
||||||
DNS.1 = *.x.com
|
|
||||||
```
|
|
||||||
|
|
||||||
> 请注意SubjectAlternativeName模块,这个地方是证书用于什么域名,多个可以用
|
|
||||||
>
|
|
||||||
> ```ini
|
|
||||||
> DNS.1 = *.x.com
|
|
||||||
> DNS.2 = *.x.com
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> 也可以指定IP
|
|
||||||
>
|
|
||||||
> ```ini
|
|
||||||
> DNS.1 = *.x.com
|
|
||||||
> DNS.2 = *.x.com
|
|
||||||
> IP.1 = xxx.xxx.xxx.xxx
|
|
||||||
> IP.2 = xxx.xxx.xxx.xxx
|
|
||||||
> ```
|
|
||||||
|
|
||||||
## 创建CSR (certificate signing request):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
openssl req -new -key x.com.key -config x.com.ini -out x.com.csr
|
|
||||||
```
|
|
||||||
|
|
||||||
可以用下列命令来查看 CSR 信息,确保它已经有了对应的私钥和主体信息:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
openssl req -in x.com.csr -noout -text
|
|
||||||
---
|
|
||||||
Certificate Request:
|
|
||||||
Data:
|
|
||||||
Version: 1 (0x0)
|
|
||||||
Subject: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com, subjectAltName = @SubjectAlternativeName
|
|
||||||
Subject Public Key Info:
|
|
||||||
Public Key Algorithm: rsaEncryption
|
|
||||||
Public-Key: (2048 bit)
|
|
||||||
Modulus:
|
|
||||||
00:d7:ef:3f:0f:50:b6:1a:43:2c:90:77:82:01:2a:
|
|
||||||
...略
|
|
||||||
5b:67:11:4c:b2:f2:51:3a:7d:77:1a:9d:cf:0e:86:
|
|
||||||
da:f7
|
|
||||||
Exponent: 65537 (0x10001)
|
|
||||||
Attributes:
|
|
||||||
(none)
|
|
||||||
Requested Extensions:
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Signature Value:
|
|
||||||
3d:3a:d4:78:81:1f:fa:29:15:6a:67:2d:6c:92:42:7f:4c:fe:
|
|
||||||
...略
|
|
||||||
01:c0:cc:f4:16:5f:d8:2e:60:e4:3e:94:e1:6e:18:8f:b3:a8:
|
|
||||||
a8:93:71:06
|
|
||||||
```
|
|
||||||
|
|
||||||
然后我们再创建一个 `x.com.crt.ini` 文件,保存以下内容,**其中SubjectAlternativeName跟上面的保持一致**
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[ server_cert ]
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid,issuer:always
|
|
||||||
keyUsage = critical, digitalSignature, keyEncipherment, dataEncipherment
|
|
||||||
extendedKeyUsage = serverAuth
|
|
||||||
|
|
||||||
subjectAltName=@SubjectAlternativeName
|
|
||||||
[ SubjectAlternativeName ]
|
|
||||||
DNS.1 = *.x.com
|
|
||||||
```
|
|
||||||
|
|
||||||
> 同样也可以多个
|
|
||||||
|
|
||||||
## 签发证书
|
|
||||||
|
|
||||||
```ini
|
|
||||||
openssl x509 \
|
|
||||||
-in x.com.csr \
|
|
||||||
-req \
|
|
||||||
-CA ca.crt \
|
|
||||||
-CAkey ca.key \
|
|
||||||
-CAserial ca.srl \
|
|
||||||
-CAcreateserial \
|
|
||||||
-extfile x.com.crt.ini \
|
|
||||||
-extensions server_cert \
|
|
||||||
-copy_extensions copyall \
|
|
||||||
-days 360 -out x.com.crt
|
|
||||||
|
|
||||||
---
|
|
||||||
Certificate request self-signature ok
|
|
||||||
subject=C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com, subjectAltName = @SubjectAlternativeName
|
|
||||||
```
|
|
||||||
|
|
||||||
> `extensions server_cert` 与`x.com.crt.ini`的标签保持一致
|
|
||||||
|
|
||||||
在以上过程中,`x.com.ini` 和 `x.com.csr` 是申请证书的客户(比如网站站长、应用开发者)生成,`x.com.crt.ini` 是签发证书的 CA 生成,`x.com.crt` 也是 CA 生成。
|
|
||||||
|
|
||||||
## 查看证书
|
|
||||||
|
|
||||||
```ini
|
|
||||||
openssl x509 -in x.com.crt -noout -text
|
|
||||||
---
|
|
||||||
Certificate:
|
|
||||||
Data:
|
|
||||||
Version: 3 (0x2)
|
|
||||||
Serial Number:
|
|
||||||
5b:3e:9f:d1:7d:8f:f2:ab:18:ba:fa:1d:d1:65:ac:4e:40:f2:e3:ac
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Issuer: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com
|
|
||||||
Validity
|
|
||||||
Not Before: Jan 12 09:49:16 2024 GMT
|
|
||||||
Not After : Jan 6 09:49:16 2025 GMT
|
|
||||||
Subject: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com, subjectAltName = @SubjectAlternativeName
|
|
||||||
Subject Public Key Info:
|
|
||||||
Public Key Algorithm: rsaEncryption
|
|
||||||
Public-Key: (2048 bit)
|
|
||||||
Modulus:
|
|
||||||
00:d7:ef:3f:0f:50:b6:1a:43:2c:90:77:82:01:2a:
|
|
||||||
...略
|
|
||||||
da:f7
|
|
||||||
Exponent: 65537 (0x10001)
|
|
||||||
X509v3 extensions:
|
|
||||||
X509v3 Basic Constraints:
|
|
||||||
CA:FALSE
|
|
||||||
X509v3 Subject Key Identifier:
|
|
||||||
AC:41:8A:AD:CB:6C:D5:68:E9:B7:59:F2:4B:E5:EF:F5:DA:50:49:C4
|
|
||||||
X509v3 Authority Key Identifier:
|
|
||||||
keyid:51:27:75:BE:3E:24:AE:A5:93:C7:1C:DE:F8:23:FB:7F:4D:BF:53:34
|
|
||||||
DirName:/C=CN/ST=Beijing/L=Beijing/O=LocalOrganizationName/OU=IT/CN=Homelab Root CA/emailAddress=admin@example.com
|
|
||||||
serial:60:9A:7A:BA:8C:98:9B:F8:1A:DE:46:C4:0C:05:0C:7F:B2:B8:C9:AB
|
|
||||||
X509v3 Key Usage: critical
|
|
||||||
Digital Signature, Key Encipherment, Data Encipherment
|
|
||||||
X509v3 Extended Key Usage:
|
|
||||||
TLS Web Server Authentication
|
|
||||||
X509v3 Subject Alternative Name:
|
|
||||||
DNS:*.x.com
|
|
||||||
Signature Algorithm: sha256WithRSAEncryption
|
|
||||||
Signature Value:
|
|
||||||
05:8e:3f:dc:a5:a8:f8:7b:ac:74:6a:c3:c7:b3:f0:33:31:ca:
|
|
||||||
...略
|
|
||||||
91:f6:40:0e
|
|
||||||
```
|
|
||||||
|
|
||||||
会看到这里已经有了签名值,它的 X509v3 Authority Key Identifier 刚好就是 CA 的 X509v3 Subject Key Identifier,它的 Public Key Modulus 和 CSR 里面的也一样。
|
|
||||||
|
|
||||||
## 验证证书
|
|
||||||
|
|
||||||
```ini
|
|
||||||
openssl verify --show_chain -CAfile ca.crt x.com.crt
|
|
||||||
---
|
|
||||||
x.com.crt: OK
|
|
||||||
Chain:
|
|
||||||
depth=0: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com, subjectAltName = @SubjectAlternativeName (untrusted)
|
|
||||||
depth=1: C = CN, ST = Beijing, L = Beijing, O = LocalOrganizationName, OU = IT, CN = Homelab Root CA, emailAddress = admin@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
至此证书生成及颁发已经完成
|
|
||||||
|
|
||||||
# 安装根证书
|
|
||||||
|
|
||||||
在整个文章中,根证书是`ca.crt`下载到设备上在安装即可。
|
|
||||||
|
|
||||||
以windows为例,直接双击打开,即可安装
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/a134652335648d6ae317be397ddcca45.png)
|
|
||||||
|
|
||||||
这里可以选择任意存储
|
|
||||||
|
|
||||||
# 配置域名证书
|
|
||||||
|
|
||||||
以nginx为例
|
|
||||||
|
|
||||||
```ini
|
|
||||||
server {
|
|
||||||
listen [::]:1234 ssl http2;
|
|
||||||
|
|
||||||
gzip off;
|
|
||||||
server_name x.com;
|
|
||||||
|
|
||||||
ssl_certificate /etc/nginx/certs/x.com.crt;
|
|
||||||
ssl_certificate_key /etc/nginx/certs/x.com.key;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
add_header Content-Type "text/html; charset=UTF-8";
|
|
||||||
return 200 "Hello, World!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
把 `ssl_certificate` 和 `ssl_certificate_key` 的值改为证书和私钥的实际路径。
|
|
||||||
|
|
||||||
执行 `sudo nginx -t` 测试配置有效性,执行 `sudo nginx -s reload` 更新配置。
|
|
||||||
|
|
||||||
在本地 hosts 配置域名解析,把 `x.com` 解析到服务器的IP地址,这个在不同操作系统上做法不同。
|
|
||||||
|
|
||||||
## 验证
|
|
||||||
|
|
||||||
以 https scheme 加端口的方式在浏览器访问,`https://x.com`
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/2ca5b19e09cad661ba0578ebd1ed610e.png)
|
|
||||||
|
|
||||||
# 总结和后续
|
|
||||||
|
|
||||||
我们介绍了一种创建自签 CA 证书的方式,并且介绍了如何使用 openssl 命令行工具创建和签发自己的证书。自签证书的好处是时效性和低成本,我们不需要有自己的服务器或者 Web 虚拟主机空间,也不需要购买域名,也不需要花时间等待 CA 做验证和恢复。
|
|
||||||
|
|
||||||
这种自签证书适用于内网 (intranet),尤其是部署安装根 CA 证书的成本很低的情形,安装了根证书后,后续所有由该根证书签发的证书都可以被系统自动信任。
|
|
||||||
|
|
||||||
TLS 可以自动使得上层的应用层服务自动地获得端到端的安全性:**1)数据完整性;2)保密性;3)真实性**,因此许多应用软件都已提供了对 TLS 的支持,包括最常见的浏览器、数据库命令行工具、远程桌面软件、常驻程序的后台管理界面等。我们可以给每一个这样的服务都签发 TLS 证书,而在终端设备上只需添加信任一次根证书,从而以低成本的方式获得信息安全性提高以及更好的隐私保障。
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: MySQL超大表删除数据
|
title: MySQL超大表删除数据
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 8ff92769
|
|
||||||
date: 2023-09-12 16:10:34
|
date: 2023-09-12 16:10:34
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: MySQL引擎介绍
|
title: MySQL引擎介绍
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: fcfd18c1
|
|
||||||
date: 2022-04-04 22:44:48
|
date: 2022-04-04 22:44:48
|
||||||
---
|
---
|
||||||
# 引擎是什么?
|
# 引擎是什么?
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
---
|
|
||||||
title: MySQL 相关知识汇总
|
title: MySQL 相关知识汇总
|
||||||
categories: []
|
categories: []
|
||||||
tags:
|
tags:
|
||||||
- MySQL
|
- MySQL
|
||||||
date: '2023-04-04T13:00:07.258Z'
|
date: '2023-04-04T13:00:07.258Z'
|
||||||
abbrlink: a3556bbe
|
|
||||||
---
|
---
|
||||||
# 1. 简介
|
# 1. 简介
|
||||||
|
|
||||||
|
|
|
@ -1,207 +0,0 @@
|
||||||
---
|
|
||||||
title: 在公司无感访问家里的服务
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: 6adf908a
|
|
||||||
date: 2024-01-11 09:05:48
|
|
||||||
---
|
|
||||||
|
|
||||||
# 简述
|
|
||||||
|
|
||||||
家里有一台ALL in Boom,跑了一些服务,在家里因为可以控制DNS,可以无感访问,在公司内就没办法使用这些服务了,所以需要一种方式,在外可以访问家里的服务,并且在常用环境做到低延迟访问
|
|
||||||
|
|
||||||
|
|
||||||
想法如下:
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/ea2ce6a84ec56d16f05659d95a24818b.png)
|
|
||||||
|
|
||||||
|
|
||||||
**家庭环境中**:由于可以控制DNS,直接在Linux主机部署一个Nginx,然后修改路由器的域名映射,将一些自己的域名直接解析到主机上。
|
|
||||||
|
|
||||||
**其他环境中**:使用CloudFlare的tunnel,提供内网穿透及域名解析服务
|
|
||||||
|
|
||||||
**公司环境中**:因为个人经常访问,如果每次都经过cloudFlare就太慢了,所以需要用一些手段加速访问。方案是frp穿透到公网,办公电脑用nginx代理到frp端口,加速访问,这样延迟大大降低。
|
|
||||||
|
|
||||||
> 为什么将clash单独列出来,是因为host文件无法生效,需要对clash做一些改动
|
|
||||||
|
|
||||||
|
|
||||||
**域名相关**
|
|
||||||
|
|
||||||
域名使用两套
|
|
||||||
|
|
||||||
xxx.com 这个是我自购的域名
|
|
||||||
xxx.net 这个是虚构的域名,只存在局域网中
|
|
||||||
|
|
||||||
# 家庭环境
|
|
||||||
|
|
||||||
## 家庭内环境介绍:
|
|
||||||
|
|
||||||
路由器:使用刷机路由,自带frp
|
|
||||||
|
|
||||||
Linux主机:由PVE虚拟化而来,固定IP,跑各种docker服务
|
|
||||||
|
|
||||||
家庭电脑:无特殊配置,仅需连接到路由器
|
|
||||||
|
|
||||||
## 路由器配置
|
|
||||||
|
|
||||||
域名配置使用了OpenWrt的主机名配置,将需要的域名指向Linux主机
|
|
||||||
|
|
||||||
> 每个路由器配置不同
|
|
||||||
|
|
||||||
## Linux主机配置
|
|
||||||
|
|
||||||
linux主机只需要配置一个nginx代理即可。
|
|
||||||
|
|
||||||
nginx我使用的[nginx proxy manager](https://nginxproxymanager.com/),上手简单,且可以浏览器管理。
|
|
||||||
|
|
||||||
使用docker-compose部署
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: '3.8'
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'jc21/nginx-proxy-manager:2.10.4'
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- '80:80'
|
|
||||||
- '84:81'
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "/bin/check-health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 3s
|
|
||||||
```
|
|
||||||
|
|
||||||
拉起容器后,可以使用 ip:84 修改一下用户名等信息,默认用户名密码:`admin@example.com/changeme`
|
|
||||||
|
|
||||||
### 配置域名代理
|
|
||||||
|
|
||||||
代理服务的端口即可
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/5b02300d1df32d5f8925363e94f33105.png)
|
|
||||||
|
|
||||||
## 测试访问
|
|
||||||
|
|
||||||
使用接入路由器的任意主机,访问这些域名,看是否能访问到
|
|
||||||
|
|
||||||
# 公网环境
|
|
||||||
|
|
||||||
公网环境需要做以下准备:
|
|
||||||
|
|
||||||
|
|
||||||
1. 自购域名,并迁移到cloudflare
|
|
||||||
2. 创建一个tunnel隧道
|
|
||||||
|
|
||||||
相关文档:
|
|
||||||
|
|
||||||
* <https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/>
|
|
||||||
|
|
||||||
**tunnel国内访问速度极慢,本方法只用于紧急访问,正常情况下基本无法使用**
|
|
||||||
|
|
||||||
## 运行tunnel隧道
|
|
||||||
|
|
||||||
在页面创建完成后,会给你部署客户端的命令,这里我是用docker创建
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/07690de58d1c280eb668739210d28df9.png)
|
|
||||||
|
|
||||||
运行完成后,就可以看到客户端了,即完成了客户端的部署
|
|
||||||
|
|
||||||
## 配置隧道
|
|
||||||
|
|
||||||
进入隧道详情,公共主机名,添加主机名
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/72601465275b0e3e44f8a53d614eab20.png)
|
|
||||||
|
|
||||||
以其中的一个域名为例
|
|
||||||
|
|
||||||
subdomain:子域名,比如blog.xxx.com,blog就是子域名
|
|
||||||
|
|
||||||
domain:域名,这里选择你迁移到cloudflare的域名
|
|
||||||
|
|
||||||
service→Type:什么协议
|
|
||||||
|
|
||||||
url:从隧道客户端访问,应该用什么样的IP和端口
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/aaf9f5464f47d443827545b9fc1a4060.png)
|
|
||||||
|
|
||||||
创建完成后,等待几分钟,即可访问
|
|
||||||
|
|
||||||
# 办公环境
|
|
||||||
|
|
||||||
公司设置是为了加速访问,所以直接通过frp访问,
|
|
||||||
|
|
||||||
## 暴漏服务
|
|
||||||
|
|
||||||
因为有一台云上的Linux主机,所以对我来说最快的方式是使用frp将服务暴漏出来,然后通过ip:port访问服务。
|
|
||||||
|
|
||||||
> frp部署本次忽略,可自行搜索教程
|
|
||||||
|
|
||||||
frp只用暴漏家内的nginx端口即可。也就是80端口,不用一个一个将服务暴漏出来。
|
|
||||||
|
|
||||||
## Nginx配置
|
|
||||||
|
|
||||||
nginx配置的模板如下
|
|
||||||
|
|
||||||
因为这里只是代理作用,使用HTTP代理会有各种各样的配置,直接用TCP代理,能简化配置流程
|
|
||||||
|
|
||||||
```ini
|
|
||||||
stream {
|
|
||||||
log_format proxy '$remote_addr [$time_local] '
|
|
||||||
'$protocol $status $bytes_sent $bytes_received '
|
|
||||||
'$session_time "$upstream_addr" '
|
|
||||||
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
|
|
||||||
access_log /Nginx/logs/tcp.log proxy ;
|
|
||||||
#将12345端口转发到192.168.1.23的3306端口
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
proxy_connect_timeout 5s;
|
|
||||||
proxy_timeout 3600s;
|
|
||||||
proxy_pass xxx.xxx.xxx.xxx:port; # 替换成自己的ip,端口
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
修改`nginx/conf/nginx.conf`,这里直接使用TCP代理即可
|
|
||||||
|
|
||||||
## Host配置
|
|
||||||
|
|
||||||
windows为例,用管理员模式修改`C:\Windows\System32\drivers\etc\hosts`文件
|
|
||||||
|
|
||||||
增加以下内容
|
|
||||||
|
|
||||||
```ini
|
|
||||||
127.0.0.1 outline.lianglianglee.com
|
|
||||||
127.0.0.1 gitea.lianglianglee.com
|
|
||||||
127.0.0.1 s3.lianglianglee.com
|
|
||||||
127.0.0.1 s3-admin.lll.net
|
|
||||||
```
|
|
||||||
|
|
||||||
修改完成后,保存
|
|
||||||
|
|
||||||
> 如遇无法保存,可以把文件复制出来,改动后再复制进去
|
|
||||||
|
|
||||||
在浏览器打开配置的域名,在控制台看目标地址及端口是否是本地的nginx端口
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/e1d4f9bef76c8478ad6c3f4b3d7e13c6.png)
|
|
||||||
|
|
||||||
# 杂项
|
|
||||||
|
|
||||||
## clash和host不兼容的问题
|
|
||||||
|
|
||||||
办公电脑配置完成后,浏览器无法访问,但是使用curl又可以访问。
|
|
||||||
|
|
||||||
顺其自然打开了浏览器的控制台,发现请求的竟然是`127.0.0.1:7890`端口,走的clash,所以无法访问
|
|
||||||
|
|
||||||
进入clash的`Settings`/`System Proxy`/`Bypass Domin/IPNet`/`Edit`
|
|
||||||
|
|
||||||
将自定义的域名加进去即可
|
|
||||||
|
|
||||||
```ini
|
|
||||||
- outline.lianglianglee.com
|
|
||||||
- gitea.lianglianglee.com
|
|
||||||
- s3.lianglianglee.com
|
|
||||||
- s3-admin.lll.net
|
|
||||||
```
|
|
||||||
|
|
||||||
重启clash,即可访问到域名
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: TrueNAS成型记
|
title: TrueNAS成型记
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: d7671edf
|
|
||||||
date: 2023-04-06 15:05:48
|
date: 2023-04-06 15:05:48
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,353 +0,0 @@
|
||||||
---
|
|
||||||
title: Outline部署教程
|
|
||||||
tags: []
|
|
||||||
categories: []
|
|
||||||
abbrlink: 9c50151f
|
|
||||||
date: 2024-01-08 11:28:22
|
|
||||||
---
|
|
||||||
|
|
||||||
# 摘要
|
|
||||||
|
|
||||||
因为日常需要写一些自己的学习笔记,文章等,因此需要一个软件用于记录和展示。市面上有很多可用的产品,比如notion,语雀,飞书等等,还有相当一部分可以私有化部署的,比如obsidian,思源笔记,typora等等都可以本地存储。这些唯一的问题是跨设备,需要全量同步数据,对我来说不是很适合。
|
|
||||||
|
|
||||||
## 期望的软件
|
|
||||||
|
|
||||||
- **纯Web应用**。设备只需要一个浏览器就可以阅读并编辑所以内容
|
|
||||||
- **可私有化部署**。作为程序员,数据还是掌握在自己手中比较好
|
|
||||||
- **占用资源小**。因为是跑在CPU及内存都惨不忍睹的NAS中的服务,所以尽量占用资源小
|
|
||||||
- **支持分享**。偶尔会把文章分享给朋友及同事,能不登陆查看文章。
|
|
||||||
|
|
||||||
综合以上期望,最后发现一个国内用户比较少的outline。https://www.getoutline.com/
|
|
||||||
|
|
||||||
# 介绍
|
|
||||||
|
|
||||||
在其github上,第一句话是
|
|
||||||
|
|
||||||
> *使用 React 和 Node.js 为您的团队构建的快速、协作、知识库。*
|
|
||||||
|
|
||||||
其目标是协作的知识库,官网介绍中也是着重介绍协作的功能。使用前端技术栈编写,界面简洁,提供SASS版本,灭月最少10刀。我选择私有化部署
|
|
||||||
|
|
||||||
查看其部署文档,我只能说有,但不多。那就抛弃官网,自己摸索吧。
|
|
||||||
|
|
||||||
## 依赖
|
|
||||||
|
|
||||||
根据其提供的env配置文件,大概需要以下组件:
|
|
||||||
|
|
||||||
- PostgreSQL(v12+)
|
|
||||||
- Redis(v4+)
|
|
||||||
- S3存储(非必须)
|
|
||||||
- 身份认证工具
|
|
||||||
|
|
||||||
外国佬的东西,全程手动,什么都要自己准备。
|
|
||||||
|
|
||||||
## 选型
|
|
||||||
|
|
||||||
**附件存储**:outline提供了两种选择,类S3存储,或本地存储。这里选择minio
|
|
||||||
|
|
||||||
**身份认证程序**:outline没有提供登录模块,需要集成第三方的登录。我这里选择使用Gitea自带的Oauth2
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
接下来按照步骤一点一点部署,所有组件都使用docker-compose部署
|
|
||||||
|
|
||||||
## 域名规划
|
|
||||||
|
|
||||||
这里只表述前缀
|
|
||||||
|
|
||||||
- **s3**:S3对象存储
|
|
||||||
- **s3-admin**:Minio控制台
|
|
||||||
- **gitea**:Gitea
|
|
||||||
- **outline**:outline的主服务
|
|
||||||
|
|
||||||
## 加速访问
|
|
||||||
|
|
||||||
因为一般都是内网访问,没必要走一圈公网,所以这里在路由器配置解析,直接把域名解析到NAS。由NAS的Nginx提供服务
|
|
||||||
|
|
||||||
# PostgreSQL&Redis&Minio
|
|
||||||
|
|
||||||
这里就直接提供docker-compose的文件。
|
|
||||||
|
|
||||||
**注意事项**
|
|
||||||
|
|
||||||
- PostgreSQL需要提前创建数据库
|
|
||||||
- Minio需要创建一个匿名访问,用于用户头像的读取
|
|
||||||
|
|
||||||
## PostgreSQL
|
|
||||||
|
|
||||||
因为文件读写权限的问题,且都是内网访问,这里用privileged开放了docker的用户权限,实际生产不建议使用
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: '3'
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:13-alpine
|
|
||||||
container_name: postgres-13
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
environment:
|
|
||||||
- POSTGRES_PASSWORD=password # feel free to change the password
|
|
||||||
volumes:
|
|
||||||
- ./postgresql/data:/var/lib/postgresql/data # persist postgres data to ~/postgres/data/ on the host
|
|
||||||
privileged: true
|
|
||||||
cpus: 2
|
|
||||||
mem_limit: 512m
|
|
||||||
```
|
|
||||||
|
|
||||||
## Redis
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: '3'
|
|
||||||
services:
|
|
||||||
redis:
|
|
||||||
image: redis:4.0.1
|
|
||||||
container_name: redis
|
|
||||||
volumes:
|
|
||||||
- ./datadir:/data
|
|
||||||
- ./conf/redis.conf:/usr/local/etc/redis/redis.conf
|
|
||||||
- ./logs:/logs
|
|
||||||
command: redis-server --requirepass password
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
```
|
|
||||||
|
|
||||||
## Minio
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: "3.7"
|
|
||||||
services:
|
|
||||||
minio:
|
|
||||||
image: "quay.io/minio/minio:RELEASE.2024-01-01T16-36-33Z"
|
|
||||||
ports:
|
|
||||||
- "9000:9000"
|
|
||||||
- "9001:9001"
|
|
||||||
volumes:
|
|
||||||
- "./minio/data1:/data1"
|
|
||||||
- "./minio/data2:/data2"
|
|
||||||
- "./minio:/data"
|
|
||||||
command: server --console-address ":9001" http://minio/data{1...2}
|
|
||||||
environment:
|
|
||||||
- MINIO_ROOT_USER=admin
|
|
||||||
- MINIO_ROOT_PASSWORD=password
|
|
||||||
```
|
|
||||||
|
|
||||||
进入控制台,创建Bucket,AccessKey
|
|
||||||
|
|
||||||
**需要添加一个匿名访问策略,用于头像访问**
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/b8c1dee5eb74cbbfb864e2e2f196891f.png)
|
|
||||||
|
|
||||||
# 身份认证程序
|
|
||||||
|
|
||||||
身份认证程序使用的Gitea
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
version: "3"
|
|
||||||
|
|
||||||
services:
|
|
||||||
server:
|
|
||||||
image: gitea/gitea:1.19.3
|
|
||||||
container_name: gitea
|
|
||||||
environment:
|
|
||||||
- GITEA__database__DB_TYPE=mysql
|
|
||||||
- GITEA__database__HOST=xxx.xxx.xxx.xxx:3306
|
|
||||||
- GITEA__database__NAME=gitea
|
|
||||||
- GITEA__database__USER=root
|
|
||||||
- GITEA__database__PASSWD=password
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./gitea:/data
|
|
||||||
- /etc/timezone:/etc/timezone:ro
|
|
||||||
- /etc/localtime:/etc/localtime:ro
|
|
||||||
ports:
|
|
||||||
- "3002:3000"
|
|
||||||
- "222:22"
|
|
||||||
```
|
|
||||||
|
|
||||||
gitea使用了MySQL作为数据存储服务
|
|
||||||
|
|
||||||
## 创建Oauth2应用
|
|
||||||
|
|
||||||
以管理员账号登录gitea后,进入管理后台,应用tab页
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/49d62f29b251c7fa0aab8e62a1b752e6.png)
|
|
||||||
|
|
||||||
重定向URL是outline的地址,这里替换成outline的域名或者IP:端口
|
|
||||||
|
|
||||||
> http://xxx.xxx.xxx/auth/oidc.callback
|
|
||||||
|
|
||||||
创建完成后会生成一堆客户端ID和密钥
|
|
||||||
|
|
||||||
![](https://static.lianglianglee.com/2024/01/ccdf3707165be5f883d7c8cbc90faa67.png)
|
|
||||||
|
|
||||||
客户端ID和密钥先找个地方记下。
|
|
||||||
|
|
||||||
# Outline部署
|
|
||||||
|
|
||||||
Outline因为太多的配置项,这里使用env文件处理,官方的env文件链接如下
|
|
||||||
|
|
||||||
https://github.com/outline/outline/blob/main/.env.sample
|
|
||||||
|
|
||||||
## 配置
|
|
||||||
|
|
||||||
env文件分为几大类
|
|
||||||
|
|
||||||
- 应用的加密配置
|
|
||||||
- PostgreSQL,Redis配置
|
|
||||||
- 应用的域名及端口配置
|
|
||||||
- 存储配置
|
|
||||||
- 身份认证配置
|
|
||||||
- 邮箱配置
|
|
||||||
- 其他
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# –––––––––––––––– REQUIRED ––––––––––––––––
|
|
||||||
|
|
||||||
NODE_ENV=production
|
|
||||||
|
|
||||||
# Generate a hex-encoded 32-byte random key. You should use `openssl rand -hex 32`
|
|
||||||
# in your terminal to generate a random value.
|
|
||||||
SECRET_KEY=d1020471380935f0053864173d8178578910ab9331a434aa1e4ec20ae6a8bb47
|
|
||||||
|
|
||||||
# Generate a unique random key. The format is not important but you could still use
|
|
||||||
# `openssl rand -hex 32` in your terminal to produce this.
|
|
||||||
UTILS_SECRET=d1020471380935f0053864173d8178578910ab9331a434aa1e4ec20ae6a8bb47
|
|
||||||
|
|
||||||
# 数据库配置
|
|
||||||
DATABASE_URL=postgres://postgres:password@xxx.xxx.xxx:5432/outline
|
|
||||||
DATABASE_URL_TEST=postgres://postgres:password@xxx.xxx.xxx:5432/outline-test
|
|
||||||
DATABASE_CONNECTION_POOL_MIN=
|
|
||||||
DATABASE_CONNECTION_POOL_MAX=
|
|
||||||
# 关闭SSL模式
|
|
||||||
PGSSLMODE=disable
|
|
||||||
|
|
||||||
# Redis配置
|
|
||||||
REDIS_URL=redis://:ll.941107@xxx.xxx.xxx:6379
|
|
||||||
|
|
||||||
# Outline的域名及端口
|
|
||||||
URL=http://outline.xxxx.com
|
|
||||||
PORT=3004
|
|
||||||
|
|
||||||
|
|
||||||
# S3配置
|
|
||||||
AWS_ACCESS_KEY_ID=YfIfejBwr2ckKJ4W9Dew
|
|
||||||
AWS_SECRET_ACCESS_KEY=mqpSPul28PoRs7T3TyEABUTT9zbz1ctcvT277qg1
|
|
||||||
AWS_REGION=cn-homelab
|
|
||||||
# AWS_S3_ACCELERATE_URL=
|
|
||||||
AWS_S3_UPLOAD_BUCKET_URL=http://s3.xxxx.com
|
|
||||||
AWS_S3_UPLOAD_BUCKET_NAME=outline-blob
|
|
||||||
AWS_S3_FORCE_PATH_STYLE=true
|
|
||||||
AWS_S3_ACL=private
|
|
||||||
|
|
||||||
# 附件存储方式:S3或者local
|
|
||||||
FILE_STORAGE=s3
|
|
||||||
|
|
||||||
# 身份认证服务的各种URL
|
|
||||||
# Redirect URI is https://<URL>/auth/oidc.callback
|
|
||||||
OIDC_CLIENT_ID=c49f442d-5c63-4394-8a56-78256c502b04
|
|
||||||
OIDC_CLIENT_SECRET=gto_v5ygxr3ym4a2w4tm3vjwebjr2tokr7jwjoob2zmh7swsq6h6jkda
|
|
||||||
OIDC_AUTH_URI=http://gitea.xxxx.com/login/oauth/authorize
|
|
||||||
OIDC_TOKEN_URI=http://gitea.xxxx.com/login/oauth/access_token
|
|
||||||
OIDC_USERINFO_URI=http://gitea.xxxx.com/login/oauth/userinfo
|
|
||||||
|
|
||||||
# Specify which claims to derive user information from
|
|
||||||
# Supports any valid JSON path with the JWT payload
|
|
||||||
OIDC_USERNAME_CLAIM=name
|
|
||||||
|
|
||||||
# Display name for OIDC authentication
|
|
||||||
OIDC_DISPLAY_NAME=Gitea
|
|
||||||
|
|
||||||
# Space separated auth scopes.
|
|
||||||
OIDC_SCOPES=openid email name
|
|
||||||
|
|
||||||
|
|
||||||
# –––––––––––––––– OPTIONAL ––––––––––––––––
|
|
||||||
|
|
||||||
# If using a Cloudfront/Cloudflare distribution or similar it can be set below.
|
|
||||||
# This will cause paths to javascript, stylesheets, and images to be updated to
|
|
||||||
# the hostname defined in CDN_URL. In your CDN configuration the origin server
|
|
||||||
# should be set to the same as URL.
|
|
||||||
# CDN_URL=
|
|
||||||
|
|
||||||
# Auto-redirect to https in production. The default is true but you may set to
|
|
||||||
# false if you can be sure that SSL is terminated at an external loadbalancer.
|
|
||||||
FORCE_HTTPS=false
|
|
||||||
|
|
||||||
# Have the installation check for updates by sending anonymized statistics to
|
|
||||||
# the maintainers
|
|
||||||
ENABLE_UPDATES=false
|
|
||||||
|
|
||||||
# 应用启动几个进程,因为只有我一个人访问,设置1即可。按照内存/512M设置数量
|
|
||||||
WEB_CONCURRENCY=1
|
|
||||||
|
|
||||||
# 最大导入大小
|
|
||||||
MAXIMUM_IMPORT_SIZE=5120000
|
|
||||||
|
|
||||||
# You can remove this line if your reverse proxy already logs incoming http
|
|
||||||
# requests and this ends up being duplicative
|
|
||||||
DEBUG=http
|
|
||||||
|
|
||||||
# Configure lowest severity level for server logs. Should be one of
|
|
||||||
# error, warn, info, http, verbose, debug and silly
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
|
|
||||||
|
|
||||||
# 邮箱的配置
|
|
||||||
SMTP_HOST=smtp.sina.com
|
|
||||||
SMTP_PORT=465
|
|
||||||
SMTP_USERNAME=xxxx@sina.com
|
|
||||||
SMTP_PASSWORD=xxxxx
|
|
||||||
SMTP_FROM_EMAIL=xxxx@sina.com
|
|
||||||
SMTP_REPLY_EMAIL=xxxx@sina.com
|
|
||||||
# SMTP_TLS_CIPHERS=
|
|
||||||
SMTP_SECURE=true
|
|
||||||
|
|
||||||
# 默认语言,这里选择中文
|
|
||||||
DEFAULT_LANGUAGE=zh_CN
|
|
||||||
|
|
||||||
# Optionally enable rate limiter at application web server
|
|
||||||
RATE_LIMITER_ENABLED=true
|
|
||||||
|
|
||||||
# Configure default throttling parameters for rate limiter
|
|
||||||
RATE_LIMITER_REQUESTS=1000
|
|
||||||
RATE_LIMITER_DURATION_WINDOW=60
|
|
||||||
|
|
||||||
|
|
||||||
# Enable unsafe-inline in script-src CSP directive
|
|
||||||
# Setting it to true allows React dev tools add-on in
|
|
||||||
# Firefox to successfully detect the project
|
|
||||||
DEVELOPMENT_UNSAFE_INLINE_CSP=false
|
|
||||||
```
|
|
||||||
|
|
||||||
如果您使用的身份认证程序不一样,则按照其文档的URL填写以下参数
|
|
||||||
|
|
||||||
- OIDC_AUTH_URI:认证接入点
|
|
||||||
- OIDC_TOKEN_URI:访问token接入点
|
|
||||||
- OIDC_USERINFO_URI:用户详情
|
|
||||||
- OIDC_USERNAME_CLAIM:简单来说用什么作为用户名,从OIDC_SCOPES选择
|
|
||||||
- OIDC_SCOPES:申请的权限,要根据身份认证程序确定有哪些权限
|
|
||||||
|
|
||||||
## 部署
|
|
||||||
|
|
||||||
```ini
|
|
||||||
version: "3.2"
|
|
||||||
services:
|
|
||||||
|
|
||||||
outline:
|
|
||||||
image: docker.getoutline.com/outlinewiki/outline:0.74.0
|
|
||||||
env_file: .env
|
|
||||||
ports:
|
|
||||||
- "3004:3004"
|
|
||||||
volumes:
|
|
||||||
- ./data:/var/lib/outline/data
|
|
||||||
```
|
|
||||||
|
|
||||||
注意:
|
|
||||||
|
|
||||||
- .env就是上面说的配置文件,需要跟docker-compose.yml同目录
|
|
||||||
- 容器内的3004是env文件的PORT配置
|
|
||||||
|
|
||||||
启动完成后,稍等片刻,即可访问http://ip:3004
|
|
||||||
|
|
||||||
# 使用手册
|
|
||||||
|
|
||||||
https://docs.getoutline.com/s/guide
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: PVE复制CentOS导致网卡启动失败的问题
|
title: PVE复制CentOS导致网卡启动失败的问题
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 98c423c7
|
|
||||||
date: 2023-11-30 14:42:03
|
date: 2023-11-30 14:42:03
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
---
|
|
||||||
title: 读《贪婪的多巴胺》第一章
|
title: 读《贪婪的多巴胺》第一章
|
||||||
tags:
|
tags:
|
||||||
- 读书
|
- 读书
|
||||||
- 杂项
|
- 杂项
|
||||||
categories:
|
categories:
|
||||||
- 读书
|
- 读书
|
||||||
abbrlink: 37dc4048
|
|
||||||
date: 2023-06-17 19:45:16
|
date: 2023-06-17 19:45:16
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 个人小网站的升级之路
|
title: 个人小网站的升级之路
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 7d78d6bb
|
|
||||||
date: 2023-04-13 13:58:25
|
date: 2023-04-13 13:58:25
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 油猴脚本保存51CTO为HTML文件
|
title: 油猴脚本保存51CTO为HTML文件
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 4d33d521
|
|
||||||
date: 2023-11-12 14:11:46
|
date: 2023-11-12 14:11:46
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 技术方案模板
|
title: 技术方案模板
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: '16911e78'
|
|
||||||
date: 2023-03-04 22:39:28
|
date: 2023-03-04 22:39:28
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 使用Cloudflare做HTTP内网穿透
|
title: 使用Cloudflare做HTTP内网穿透
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 383a561d
|
|
||||||
date: 2023-12-11 11:39:18
|
date: 2023-12-11 11:39:18
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
|
||||||
title: 使用油猴脚本保存极客时间文章
|
title: 使用油猴脚本保存极客时间文章
|
||||||
tags: []
|
tags: []
|
||||||
categories: []
|
categories: []
|
||||||
abbrlink: 62a77eea
|
|
||||||
date: 2023-08-03 16:58:17
|
date: 2023-08-03 16:58:17
|
||||||
---
|
---
|
||||||
# 背景
|
# 背景
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e0fbe04d7d89626a2e700ffdc47f4116e925f9ca
|
Subproject commit afee0b2ba54730328d1a972d4ab13e9af61f3ce8
|
Loading…
Reference in New Issue