我的VPS服务部署记录
本文记录了在 CentOS 7 VPS 服务器上部署各种服务的详细步骤,包括服务器初始化、Docker 环境配置、以及多个自托管服务的部署过程。
我的 VPS 使用的是 CentOS 7 服务器,所以以下操作都是基于 CentOS 系统。
服务器设置
备份旧的 yum 源:
mkdir -p /etc/yum.repos.d/bak
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/
配置 CentOS 7 源:
curl -o /etc/yum.repos.d/Centos7-aliyun.repo https://mirrors.wlnmp.com/centos/Centos7-aliyun-x86_64.repo
清理缓存并重建缓存:
yum clean all
yum makecache
更新 yum 源:
yum update
安装常用软件:
yum install git vim jq ntp -y
设置时钟同步:
systemctl start ntpd
systemctl enable ntpd
ntpdate pool.ntp.org
设置时区为上海时区:
# 查看当前时区
timedatectl
# 设置时区为上海(Asia/Shanghai)
timedatectl set-timezone Asia/Shanghai
# 验证时区设置
timedatectl
date
[可选] 设置系统 Swap 交换分区
因为 vps 服务器的运行内存很小,所以这里先设置下 Swap
# 1GB RAM with 2GB Swap
sudo fallocate -l 2G /swapfile && \
sudo dd if=/dev/zero of=/swapfile bs=1024 count=2097152 && \
sudo chmod 600 /swapfile && \
sudo mkswap /swapfile && \
sudo swapon /swapfile && \
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab && \
sudo swapon --show && \
sudo free -h
安装 Nginx
参考 CentOS 7 下 yum 安装和配置 Nginx ,使用 yum 安装:
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install nginx -y
systemctl enable nginx
打开防火墙端口:
yum install firewalld -y
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --reload
使用反向代理需要打开 SELinux 网络访问权限:
setsebool -P httpd_can_network_connect on
安装并生成证书
域名托管在 CloudFlare,使用 acme.sh 通过 DNS API 自动申请和续期 SSL 证书。参考 acme.sh DNS API 文档。
准备工作:
- 在 CloudFlare 获取 API Token 或 Global API Key
- 创建 SSL 证书存储目录
# 创建 SSL 证书目录
mkdir -p /etc/nginx/ssl
# 安装 acme.sh
curl https://get.acme.sh | sh -s email=ichensoul@gmail.com
# 配置 CloudFlare API 凭证(使用 API Token 或 Global API Key)
export CF_Key="XXXXXXXXXXXXXXXXXX" # CloudFlare Global API Key
export CF_Email="ichensoul@gmail.com" # CloudFlare 账户邮箱
# 或者使用 API Token(推荐)
export CF_Token="your_api_token"
export CF_Account_ID="your_account_id"
# 申请证书(支持通配符域名)
~/.acme.sh/acme.sh --issue --server letsencrypt --dns dns_cf -d chensoul.cc -d '*.chensoul.cc'
# 复制证书到 Nginx 目录
cp ~/.acme.sh/chensoul.cc_ecc/{chensoul.cc.cer,chensoul.cc.key,fullchain.cer,ca.cer} /etc/nginx/ssl/
# 安装证书并设置自动续期
~/.acme.sh/acme.sh --installcert -d chensoul.cc -d *.chensoul.cc \
--cert-file /etc/nginx/ssl/chensoul.cc.cer \
--key-file /etc/nginx/ssl/chensoul.cc.key \
--fullchain-file /etc/nginx/ssl/fullchain.cer \
--ca-file /etc/nginx/ssl/ca.cer \
--reloadcmd "nginx -s reload"
注意:证书会自动续期,续期命令已添加到 crontab 中。
Docker 安装和配置
一键安装docker和docker compose:
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
启动 Docker 服务:
systemctl enable docker
systemctl start docker
# 验证安装
docker --version
docker ps
查看docker配置文件,默认会给我们配置刚才选择的镜像加速地址
cat /etc/docker/daemon.json
设置 iptables 允许流量转发:
iptables -P FORWARD ACCEPT
参考 Best Practice: Use a Docker network,创建一个自定义的网络:
docker network create vps
查看 docker 网络:
docker network ls
NETWORK ID NAME DRIVER SCOPE
68f4aeaa57bd bridge bridge local
6a96b9d8617e vps bridge local
4a8679e35f4d host host local
ba21bef23b04 none null local
注意:bridge、host、none 是内部预先创建的网络。
服务部署
Postgres
PostgreSQL 是一个功能强大的开源关系型数据库管理系统,作为其他服务的数据存储后端。
创建 postgres.yaml 文件:
services:
postgres:
image: postgres:18
restart: always
ports:
- "5435:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: vps@027!
TZ: Asia/Shanghai
healthcheck:
test:
["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"]
interval: 5s
timeout: 10s
retries: 5
networks:
- vps
networks:
vps:
external: true
启动服务:
docker compose -f postgres.yaml up -d
# 查看日志
docker logs -f postgres
# 验证数据库连接
docker exec -it postgres psql -U postgres -d postgres
Memos
Memos 是一个开源的、自托管的备忘录和知识管理系统,支持 Markdown、标签、搜索等功能。
- 在 postgres 容器创建 memos 数据库:
docker exec -it postgres psql -U postgres
CREATE DATABASE memos OWNER postgres;
- 通过 docker compose 安装,创建
memos.yaml:
services:
memos:
image: neosmemo/memos:0.18.2
container_name: memos
environment:
- MEMOS_DRIVER=postgres
- MEMOS_DSN=postgres://postgres:vps@027!@postgres:5432/memos?sslmode=disable
volumes:
- ~/.memos/:/var/opt/memos
ports:
- '5230:5230'
networks:
- vps
networks:
vps:
external: true
版本说明:
- 0.18.2 版本:功能丰富,包括电报机器人、webhook、S3 存储和自定义 CDN 域名等。支持多数据库(PostgreSQL、MySQL、SQLite)。
- 0.14.4 版本:轻量级版本,无评论功能,仅支持 SQLite3。
- 启动服务:
docker compose -f memos.yaml up -d
docker logs -f memos
- 配置 nginx 配置文件
/etc/nginx/conf.d/memos.conf:
server {
listen 80;
listen [::]:80;
server_name memos.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name memos.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:5230;
}
}
- 自定义样式(可选):
美化标签样式,在 Memos 设置中添加自定义 CSS:
.status-text{font-size:10px !important;border:none;color:rgb(156,163,175) !important;}
.tag-span,.dark .tag-span{border: 1px solid;border-radius:6px;padding:0px 6px;color:rgb(22,163,74) !important;font-size:12px !important;-webkit-transform: scale(calc(10 / 12));transform-origin: left center;}
.memo-content-text .link{color:rgb(22,163,74) !important;margin-right:-6px;}
header .bg-blue-600{display:none !important;}
.text-lg {font-size: 1rem !important;}
.header-wrapper,.sidebar-wrapper{width: 11rem !important;}
.filter-query-container{padding-bottom:0.5rem;}
- 重新加载 Nginx 配置并访问服务:
nginx -s reload
访问 https://memos.chensoul.cc/ ,默认用户名和密码为 admin/memos。登录之后,请立即修改密码。
N8n
N8n 是一个开源的工作流自动化工具,可以通过可视化界面创建自动化工作流,连接各种服务和 API。
- 在 postgres 容器创建 n8n 数据库:
docker exec -it postgres psql -U postgres
CREATE DATABASE n8n OWNER postgres;
- 通过 docker compose 安装,创建
n8n.yaml:
services:
n8n:
image: n8nio/n8n
container_name: n8n
restart: always
environment:
- NODE_ENV=production
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=postgres
- DB_POSTGRESDB_PASSWORD=vps@027!
- TZ="Asia/Shanghai"
- GENERIC_TIMEZONE="Asia/Shanghai"
- N8N_DEFAULT_LOCALE=zh-CN
# 是否启用诊断和个性化推荐
- N8N_DIAGNOSTICS_ENABLED=false
- N8N_PERSONALIZATION_ENABLED=false
# 是否在启动时重新安装缺失的包
- N8N_REINSTALL_MISSING_PACKAGES=true
- WEBHOOK_URL=https://n8n.chensoul.cc/
- N8N_HOST=n8n.chensoul.cc
- N8N_ENCRYPTION_KEY=2cc5b5f9e31b43ff3817c1d04e5fa735
ports:
- '5678:5678'
networks:
- vps
networks:
vps:
external: true
- 启动服务:
docker compose -f n8n.yaml up -d
docker logs -f n8n
- 配置 nginx 配置文件
/etc/nginx/conf.d/n8n.conf:
server {
listen 80;
listen [::]:80;
server_name n8n.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name n8n.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection 'upgrade';
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Origin 'https://n8n.chensoul.cc';
access_log /var/log/nginx/n8n.log combined buffer=128k flush=5s;
}
}
故障排查:如果出现
Origin header does NOT match the expected origin. (Origin: "n8n.chensoul.cc", Expected: "127.0.0.1:5678")错误,需要在 nginx 配置里添加proxy_set_header Origin 'https://n8n.chensoul.cc';
- 重新加载 Nginx 配置并访问服务:
nginx -t
nginx -s reload
- 创建工作流(Workflows):
参考这篇文章 http://stiles.cc/archives/237/ ,目前我配置了以下 workflows,实现了 github、douban、rss、memos 同步到 Telegram。
workflows 参考:
Bark
Bark 是一个 iOS 应用,允许你向 iPhone 推送自定义通知。通过自建服务器,可以实现消息推送的完全控制。
项目地址:https://github.com/Finb/Bark
在 iOS 上安装 Bark 应用
服务端使用 Docker 安装:
docker run -dt --name bark -p 8090:8080 -v /data/bark://data finab/bark-server
在 iOS Bark 应用上添加私有服务器:
http://x.x.x.x:8090测试推送功能:
# 替换 <device_key> 为你的设备密钥
curl -X "POST" "http://x.x.x.x:8090/<device_key>" \
-H 'Content-Type: application/json; charset=utf-8' \
-d '{
"body": "这是一个测试",
"title": "Test Title",
"badge": 1,
"category": "myNotificationCategory",
"icon": "https://www.usememos.com/logo-rounded.png",
"group": "test"
}'
配置 nginx 配置文件
/etc/nginx/conf.d/bark.conf:server { listen 80; listen [::]:80; server_name bark.chensoul.cc; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name bark.chensoul.cc; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8090; } }重新加载 Nginx 配置:
nginx -t
nginx -s reload
Planka
Planka 是一个实时看板工具,使用 React 和 Redux 构建,可以作为 Trello 的开源替代品。
项目地址:https://github.com/plankanban/planka
安装步骤参考 官方文档。
- 创建
planka.yaml文件,配置使用已安装的 PostgreSQL 数据库:
services:
planka:
image: ghcr.io/plankanban/planka:latest
container_name: planka
restart: on-failure
volumes:
- /data/planka/user-avatars://app/public/user-avatars
- /data/planka/project-background-images://app/public/project-background-images
- /data/planka/attachments://app/private/attachments
ports:
- "1337:1337"
environment:
- BASE_URL=http://localhost:1337/
- DATABASE_URL=postgresql://postgres:vps@027!@postgres:5432/planka
- SECRET_KEY=notsecretkey
# - TRUST_PROXY=0
# - TOKEN_EXPIRES_IN=365 # In days
# related: https://github.com/knex/knex/issues/2354
# As knex does not pass query parameters from the connection string we
# have to use environment variables in order to pass the desired values, e.g.
# - PGSSLMODE=<value>
# Configure knex to accept SSL certificates
# - KNEX_REJECT_UNAUTHORIZED_SSL_CERTIFICATE=false
# - DEFAULT_ADMIN_EMAIL=demo@demo.demo # Do not remove if you want to prevent this user from being edited/deleted
- DEFAULT_ADMIN_PASSWORD=demo
- DEFAULT_ADMIN_NAME=Demo Demo
- DEFAULT_ADMIN_USERNAME=demo
# - SHOW_DETAILED_AUTH_ERRORS=false # Set to true to show more detailed authentication error messages. It should not be enabled without a rate limiter for security reasons.
# - ALLOW_ALL_TO_CREATE_PROJECTS=true
# - S3_ENDPOINT=
# - S3_REGION=
# - S3_ACCESS_KEY_ID=
# - S3_SECRET_ACCESS_KEY=
# - S3_BUCKET=
# - S3_FORCE_PATH_STYLE=true
# - OIDC_ISSUER=
# - OIDC_CLIENT_ID=
# - OIDC_CLIENT_SECRET=
# - OIDC_ID_TOKEN_SIGNED_RESPONSE_ALG=
# - OIDC_USERINFO_SIGNED_RESPONSE_ALG=
# - OIDC_SCOPES=openid email profile
# - OIDC_RESPONSE_MODE=fragment
# - OIDC_USE_DEFAULT_RESPONSE_MODE=true
# - OIDC_ADMIN_ROLES=admin
# - OIDC_CLAIMS_SOURCE=userinfo
# - OIDC_EMAIL_ATTRIBUTE=email
# - OIDC_NAME_ATTRIBUTE=name
# - OIDC_USERNAME_ATTRIBUTE=preferred_username
# - OIDC_ROLES_ATTRIBUTE=groups
# - OIDC_IGNORE_USERNAME=true
# - OIDC_IGNORE_ROLES=true
# - OIDC_ENFORCED=true
# Email Notifications (https://nodemailer.com/smtp/)
# - SMTP_HOST=
# - SMTP_PORT=587
# - SMTP_NAME=
# - SMTP_SECURE=true
# - SMTP_USER=
# - SMTP_PASSWORD=
# - SMTP_FROM="Demo Demo" <demo@demo.demo>
# - SMTP_TLS_REJECT_UNAUTHORIZED=false
# Optional fields: accessToken, events, excludedEvents
# - |
# WEBHOOKS=[{
# "url": "http://localhost:3001",
# "accessToken": "notaccesstoken",
# "events": ["cardCreate", "cardUpdate", "cardDelete"],
# "excludedEvents": ["notificationCreate", "notificationUpdate"]
# }]
# - SLACK_BOT_TOKEN=
# - SLACK_CHANNEL_ID=
# - GOOGLE_CHAT_WEBHOOK_URL=
# - TELEGRAM_BOT_TOKEN=
# - TELEGRAM_CHAT_ID=
# - TELEGRAM_THREAD_ID=
networks:
- vps
networks:
vps:
external: true
- 在 postgres 容器创建 planka 数据库:
docker exec -it postgres psql -U postgres
CREATE DATABASE planka OWNER postgres;
\q
- 启动服务:
docker compose -f planka.yaml up -d
docker logs -f planka
- 配置 nginx 配置文件
/etc/nginx/conf.d/planka.conf:
server {
listen 80;
listen [::]:80;
server_name planka.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name planka.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:1337;
}
}
- 重新加载 Nginx 配置并访问服务:
nginx -t
nginx -s reload
访问 https://planka.chensoul.cc/,使用默认账号 demo/demo 登录(可在配置文件中修改)。
Umami
Umami 是一个简单、快速、注重隐私的网站分析工具,可以作为 Google Analytics 的开源替代品。
- 在 postgres 容器创建 umami 数据库:
docker exec -it postgres psql -U postgres
CREATE DATABASE umami OWNER postgres;
- 通过 docker compose 安装,创建
umami.yaml:
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: umami
ports:
- "3003:3000"
environment:
DATABASE_URL: postgresql://postgres:vps@027!@postgres:5432/umami
DATABASE_TYPE: postgresql
HASH_SALT: vps@2025
TRACKER_SCRIPT_NAME: random-string.js
TZ: "Asia/Shanghai"
GENERIC_TIMEZONE: "Asia/Shanghai"
networks:
- vps
restart: always
networks:
vps:
external: true
参考 https://eallion.com/umami/,Umami 的默认跟踪代码是被大多数的广告插件屏蔽的,被屏蔽了你就统计不到访客信息了。如果需要反屏蔽,需要在 docker compose.yml 文件中添加环境变量:TRACKER_SCRIPT_NAME,如:
environment:
TRACKER_SCRIPT_NAME: random-string.js
然后获取到的跟踪代码的 src 会变成:
srcipt.js => random-string.js
启动:
docker compose -f umami.yaml up -d
docker logs -f umami
设置自定义域名:
umami.chensoul.cc配置 nginx 配置文件
/etc/nginx/conf.d/umami.conf:
server {
listen 80;
listen [::]:80;
server_name umami.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name umami.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:3003;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
# 缓存
add_header Cache-Control no-cache;
expires 12h;
}
}
- 重新加载 Nginx 配置并访问服务:
nginx -t
nginx -s reload
访问 https://umami.chensoul.cc/,默认用户名和密码为 admin/umami。登录之后,请立即修改密码,并添加要统计的网站。
Kuma (Uptime Kuma)
Uptime Kuma 是一个易于使用的自托管监控工具,可以监控网站和服务的可用性。
项目地址:https://github.com/louislam/uptime-kuma
使用 docker compose 部署,创建 uptime.yaml:
services:
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
volumes:
- ~/.uptime-kuma://app/data
ports:
- 3001:3001
restart: always
networks:
- vps
networks:
vps:
external: true
启动服务:
docker compose -f uptime.yaml up -d
docker logs -f uptime-kuma
配置 nginx 配置文件 /etc/nginx/conf.d/uptime.conf:
server {
listen 80;
listen [::]:80;
server_name uptime.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name uptime.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
重新加载 Nginx 配置并访问服务:
nginx -t
nginx -s reload
访问 https://uptime.chensoul.cc/,首次访问需要设置管理员账号。
升级服务:
docker compose -f uptime.yaml down
docker pull louislam/uptime-kuma:1
docker compose -f uptime.yaml up -d
karakeep
karakeep 是一款可自托管的书签应用程序,带有 AI 智能功能,适合数据收集爱好者使用。
项目地址:https://github.com/karakeep-app/karakeep
- 通过 docker compose 安装,创建
karakeep.yaml:
services:
web:
image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release}
container_name: karakeep
restart: unless-stopped
volumes:
- /data/karakeep:/data
ports:
- "3002:3000"
environment:
NEXTAUTH_SECRET: super_random_string
MEILI_MASTER_KEY: another_random_string
NEXTAUTH_URL: https://karakeep.chensoul.cc
MEILI_ADDR: http://meilisearch:7700
BROWSER_WEB_URL: http://chrome:9222
# OPENAI_API_KEY: ...
DATA_DIR: /data
chrome:
image: gcr.io/zenika-hub/alpine-chrome:124
restart: unless-stopped
command:
- --no-sandbox
- --disable-gpu
- --disable-dev-shm-usage
- --remote-debugging-address=0.0.0.0
- --remote-debugging-port=9222
- --hide-scrollbars
meilisearch:
image: getmeili/meilisearch:v1.13.3
restart: unless-stopped
environment:
MEILI_NO_ANALYTICS: "true"
volumes:
- meilisearch:/meili_data
networks:
- vps
networks:
vps:
external: true
volumes:
meilisearch:
- 启动服务:
docker compose -f karakeep.yaml up -d
docker logs -f karakeep
- 配置 nginx 配置文件
/etc/nginx/conf.d/karakeep.conf:
server {
listen 80;
listen [::]:80;
server_name karakeep.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name karakeep.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:3002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
expires 12h;
}
}
- 重新加载 Nginx 配置:
nginx -t
nginx -s reload
- 使用 API 接口导入 URL(可选):
先创建 API Key,然后在 karakeep 设置中获取。
查询 memos 数据库(使用 PostgreSQL)中包含 URL 链接的记录:
SELECT (regexp_matches(content, 'https?://\S+', 'g'))[1] AS url FROM memo where content like '%https:%'
将查询结果保存为 all_links.txt
然后运行导入命令:
while IFS= read -r url; do
docker run --rm ghcr.io/karakeep-app/karakeep-cli:release --api-key "ak1_066c79d8a9d634d4b826_d99f3a2732cab381f7c9" --server-addr "https://karakeep.chensoul.cc/" bookmarks add --link "$url"
done < all_links.txt
Blinko
Blinko 是一个AI驱动的卡片笔记项目,专为那些想要快速捕捉和组织灵感的人设计。它允许用户在灵感闪现的瞬间无缝记录想法,确保不错过任何创意火花。
创建 blinko.yaml 文件:
services:
blinko:
image: blinkospace/blinko:latest
container_name: blinko
environment:
NODE_ENV: production
NEXTAUTH_SECRET: my_ultra_secure_nextauth_secret
DATABASE_URL: postgresql://postgres:vps@027!@postgres:5432/blinko
restart: always
ports:
- "1111:1111"
healthcheck:
test: ["CMD", "curl", "-f", "http://blinko:1111/"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
networks:
- vps
networks:
vps:
external: true
- 创建数据库:
docker exec -it postgres psql -d postgres -U postgres
CREATE DATABASE blinko;
\q
- 启动服务:
docker compose -f blinko.yaml up -d
docker logs -f blinko
- 配置 nginx 配置文件
/etc/nginx/conf.d/blinko.conf:
server {
listen 80;
listen [::]:80;
server_name blinko.chensoul.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name blinko.chensoul.cc;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/chensoul.cc.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:1111;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
add_header Cache-Control no-cache;
expires 12h;
}
}
- 重新加载 Nginx 配置:
nginx -t
nginx -s reload
服务升级
使用 Watchtower 自动更新 Docker 镜像与容器。Watchtower 会定期检查容器镜像更新,并自动重启容器使用新镜像。
# 每天凌晨3点05分更新
docker run -d \
--name watchtower \
--restart always \
-e TZ=Asia/Shanghai \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--cleanup \
-s "0 5 3 * * *"
注意:Watchtower 会自动更新所有容器。如果只想更新特定容器,可以使用标签过滤功能。
数据库备份和恢复
定期备份数据库是保障数据安全的重要措施。以下脚本实现了自动备份 PostgreSQL 数据库并推送到 Git 仓库。
PostgreSQL 数据库备份
备份脚本:/opt/vps-backup/scripts/backup_database.sh
#!/bin/bash
CONTAINER_NAME="postgres"
BACKUP_DIR="/opt/vps-backup/database"
BACKUP_PREFIX=postgres
BACKUP_POSTFIX=$(date +%Y%m%d_%H)
DATABASES=("memos" "n8n" "umami" "blinko")
mkdir -p $BACKUP_DIR
for DB_NAME in "${DATABASES[@]}"
do
BACKUP_FILE="${BACKUP_PREFIX}_${DB_NAME}_${BACKUP_POSTFIX}.sql"
echo "docker exec -it $CONTAINER_NAME pg_dump -U postgres $DB_NAME > $BACKUP_DIR/$BACKUP_FILE"
docker exec -it $CONTAINER_NAME pg_dump -U postgres $DB_NAME > $BACKUP_DIR/$BACKUP_FILE
if [ $? -eq 0 ]; then
echo "DB $DB_NAME backup success: $BACKUP_FILE"
else
echo "DB $DB_NAME backup fail"
fi
done
# 删除超过3天的备份文件
find $BACKUP_DIR -name "${BACKUP_PREFIX}_*.sql" -type f -mtime +3 -exec rm -f {} \;
cd /opt/vps-backup
git pull
git add .
git commit -m "backup database for $BACKUP_POSTFIX"
git push origin main
数据库恢复
恢复数据库备份:
# 恢复 memos 数据库
docker cp /opt/vps-backup/database/postgres_memos_20251111_12.sql postgres:/tmp/
docker exec -it postgres psql -U postgres -d memos -f /tmp/postgres_memos_20251111_12.sql
# 恢复 umami 数据库
docker cp /opt/vps-backup/database/postgres_umami_20251111_12.sql postgres:/tmp/
docker exec -it postgres psql -U postgres -d umami -f /tmp/postgres_umami_20251111_12.sql
N8n 工作流备份
备份脚本:/opt/vps-backup/scripts/backup_n8n.sh
#!/bin/bash
DATE=$(date +%Y%m%d)
BACKUP_DIR="/opt/vps-backup/n8n"
mkdir -p $BACKUP_DIR/$DATE
cd $BACKUP_DIR
docker exec -u node -it n8n n8n export:workflow --backup --output=./$DATE
docker cp n8n://home/node/$DATE ${BACKUP_DIR}
cd ${BACKUP_DIR}/$DATE
for file in `ls`; do
filename=$(cat "$file" | jq -r '.name')
mv "$file" "$filename".json
done
docker exec -u node -it n8n n8n export:credentials --all --output=./credentials.json
docker cp n8n://home/node/credentials.json ${BACKUP_DIR}
# 删除超过3天的备份目录
find $BACKUP_DIR -type d -mtime +3 -exec rm -rf {} \;
cd /opt/vps-backup
git pull
git add .
git commit -m "backup n8n files for $DATE"
git push origin main
定时任务
使用 crontab 设置定时任务,实现自动化运维:
# 编辑 crontab
crontab -e
# 添加以下任务:
# SSL 证书自动续期(每天1点58分)
58 1 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
# 时钟同步(每20分钟)
*/20 * * * * /usr/sbin/ntpdate pool.ntp.org > /dev/null 2>&1
# 数据库备份(每3小时)
0 */3 * * * sh /opt/vps-backup/scripts/backup_database.sh
# N8n 工作流备份(每天凌晨2点)
0 2 * * * sh /opt/vps-backup/scripts/backup_n8n.sh
