一台闲置的 Android 手机,跑起 Termux + proot-distro 的 Ubuntu 容器,就能承载博客、图库、搜索引擎、词典、网盘、对象存储、内网穿透、代理、数据库等十几个服务。本文从零开始,把环境搭建、核心服务部署、公网访问与运维排错整合成一份完整指南。


1. Termux 入门与基础配置

Termux 是安卓无 root 运行的 Linux 终端模拟器,可以把一台闲置手机变成便携式 Linux 服务器。

1.1 安装与首次配置

版本注意:不要安装 Google Play 上的旧版 Termux,建议从 F-Droid 或 GitHub Releases 下载最新 APK,系统需 Android 7.0+。

装好之后,按顺序做三件事:

# 1. 更新软件包
pkg update && pkg upgrade -y

# 2. 换国内镜像源(解决下载慢)
termux-change-repo
# 音量加减键移动光标,空格键选中 Mirrors in Chinese Mainland,回车 OK

# 3. 访问手机本地存储
termux-setup-storage

授权存储后,内部存储创建 storage 目录,Termux 通过 ~/storage 访问手机文件。

1.2 保活(防止锁屏被杀)

termux-wake-lock      # 启用唤醒锁
termux-wake-unlock # 释放

Android 系统层面,还需要:设置 → 应用 → Termux → 电池 → 无限制;多任务卡片锁定 Termux;系统自启动管理中允许 Termux。安卓 12+ 务必加入电池白名单,否则后台容易被杀。

1.3 常用命令速查

pkg install <包名>       # 安装软件
pkg uninstall <包名> # 卸载
pkg search <关键词> # 搜索
pkg list-installed # 查看已安装

ls / cd / pwd / mkdir / rm / cp / mv # 文件操作
pkg install git curl wget nano unzip htop neofetch # 常用工具
pkg install python # Python

注意事项:Termux 不能直接运行 APK;不要用 sudo(没有真正 root);卸载 Termux 会清空全部内部数据;不要随意执行来路不明的脚本。

1.4 proot-distro Ubuntu 容器

pkg update && pkg install -y proot proot-distro tar

# 离线导入 rootfs
mkdir -p $PREFIX/var/lib/proot-distro/dlcache/

# 创建文件夹
mkdir -p $PREFIX/var/lib/proot-distro/dlcache/

cp /storage/emulated/0/Download/ubuntu-noble-aarch64-pd-v4.18.0.tar.xz \
$PREFIX/var/lib/proot-distro/dlcache/

proot-distro install $PREFIX/var/lib/proot-distro/dlcache/ubuntu-noble-aarch64-pd-v4.18.0.tar.xz

# 重命名并登录
proot-distro rename ubuntu-noble-aarch64-pd-v4.18.0 ubuntu
proot-distro login ubuntu --bind $PREFIX/etc/resolv.conf:/etc/resolv.conf

Termux .bashrc文件:

alias on='proot-distro login ubuntu --bind /storage/emulated/0/Ubuntu:/root/home'

termux-wake-lock

首次进入设置 DNS 与国内 ARM 源:

echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 223.5.5.5" >> /etc/resolv.conf

cat > /etc/apt/sources.list.d/ubuntu.sources <<'EOF'
Types: deb
URIs: https://mirrors.aliyun.com/ubuntu-ports
Suites: noble noble-updates noble-backports noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF

apt update && apt upgrade -y

在 Termux 宿主设置 alias 一键登录:

echo "alias ubuntu='proot-distro login ubuntu --bind $PREFIX/etc/resolv.conf:/etc/resolv.conf'" >> ~/.bashrc
source ~/.bashrc

容器化 Ubuntu 的特点:

特性 说明
架构 ARM64(aarch64)
包管理 apt(完整 Ubuntu 仓库)
无 systemd 服务需手动启动或通过 profile.d 脚本
root 模拟 proot 模拟的 root 权限,非真 root
资源损耗 CPU 约 12-18%,I/O 约 30-50%

两个关键边界要牢记:没有 systemd(服务启动方式要特别处理)和 root 是模拟的(不能依赖特权操作),这在后续部署中会反复遇到。


2. Ubuntu Server 安装与基础配置

环境:Ubuntu 22.04.5 LTS Server 版 | VMware 虚拟机 | 网卡 ens33 | 静态 IP 192.168.44.10

2.1 系统安装

下载 Ubuntu 22.04.5 LTS Server 镜像,VMware 新建虚拟机(典型配置),预留 2 核 CPU、2G 内存、30G 磁盘。安装关键选项:

  • 语言推荐 English(服务器环境避免中文乱码);
  • 网络默认 DHCP,装完再改静态 IP;
  • 镜像源可替换为 http://mirrors.aliyun.com/ubuntu;
  • 磁盘分区选 Use an entire disk(如需关闭 LVM 可取消 Set up this disk as an LVM group);
  • SSH 服务(必选):勾选 Install OpenSSH server,否则无法远程连接。

2.2 配置静态 IP(Netplan 新版写法)

先禁用 cloud-init 网络管理(否则重启 IP 变回 DHCP):

sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg <<-'EOF'
network: {config: disabled}
EOF

写入 Netplan 配置,用 routes 替代已废弃的 gateway4:

network:
ethernets:
ens33:
dhcp4: no
addresses: [192.168.44.10/24]
routes:
- to: default
via: 192.168.44.2
nameservers:
addresses: [223.5.5.5, 114.114.114.114]
version: 2

安全应用:sudo netplan try(120 秒超时自动回滚,防止 SSH 失联)。验证:ip a、ip route、ping mirrors.aliyun.com。

2.3 精简登录 MOTD 提示

sudo chmod -x /etc/update-motd.d/10-help-text                    # 文档链接行
sudo chmod -x /etc/update-motd.d/91-contract-ua-esm-status # ESM/订阅提示
sudo chmod -x /etc/update-motd.d/91-release-upgrade # 新版本升级提示
sudo chmod -x /etc/update-motd.d/90-updates-available # 更新数量提示
sudo chmod -x /usr/share/landscape/landscape-sysinfo.wrapper # 系统负载/内存/IP

sudo tee /etc/update-manager/release-upgrades <<-'EOF'
[DEFAULT]
Prompt=never
EOF

sudo rm -rf /var/lib/update-manager

SSH 客户端显示的「连接主机… 连接主机成功」是本地软件输出,不属于系统 MOTD,服务器端无法关闭。

2.4 更换国内源与常用工具

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak   # 备份
# 写入阿里云源(jammy 系列各 deb/deb-src 行)

sudo apt update && sudo apt upgrade -y
sudo apt install -y net-tools vim curl wget git

3. proot 容器服务自启动原理

很多人以为「把服务脚本放进 /etc/profile.d 就能开机自启」,这句话只说对了一半。

3.1 /etc/profile.d 到底何时执行

关键结论:/etc/profile 会加载 /etc/profile.d/*.sh,而 /etc/profile 仅在登录 shell(bash -l)才执行。

场景 是否执行 /etc/profile.d
proot-distro run ubuntu bash -l(登录 shell) ✅ 执行
proot-distro run ubuntu bash(普通 shell) ❌ 不执行
后台服务、systemd ❌ 不读取

所以把服务脚本丢进 /etc/profile.d/,只能实现「手动进入交互式登录容器时启动」,不能实现后台开机自启。

3.2 交互式登录自动启动的用法

# 写脚本 /etc/profile.d/myservice.sh
#!/bin/bash
echo ">>> 启动我的服务"
# service nginx start
# nohup /opt/myapp >/opt/myapp.log 2>&1 &

chmod +x /etc/profile.d/myservice.sh

# 必须以登录 shell 进入
proot-distro login ubuntu -- bash -l

3.3 三个必须避开的坑

  1. proot-distro login ubuntu 默认不是登录 shell(不带 -l),脚本不会跑;
  2. 多次进入容器会重复执行脚本,需加进程检测:
    if ! pgrep -f "nginx" >/dev/null ;then
    service nginx start
    fi
  3. 这不是真正的开机自启——Termux 重启、容器没运行时不会自动跑;proot Ubuntu 无 systemd。

3.4 三种真正可落地的方案

方案 触发时机 缺点 使用条件
A. /etc/profile.d 手动登录进入交互式 shell 不登录不启动;重复执行;不能常驻 必须 -- bash -l
B. proot-distro 启动钩子 容器启动就运行 — 修改 /data/data/com.termux/files/usr/etc/proot-distro/ubuntu.sh
C. Termux 侧自启动 Termux 开机先启容器 proot 会话结束进程销毁 需 tmux 套一层常驻

方案 C 的 tmux 常驻示例:

tmux new-session -d -s ubuntu_srv "proot-distro login ubuntu -- bash -c 'service nginx start; sleep infinity'"

结论:profile.d 方案成立的前提是「可执行权限 + bash -l 登录 + 进程检测」,但它不等于开机自启。需要真正常驻时,请用启动钩子或 Termux 侧 tmux。


4. Nginx 网关与站点配置

Nginx 作为统一网关,4 个站点按端口分发,静态托管与反向代理各司其职。

4.1 安装与配置结构

apt update && apt install -y nginx
nginx -v # nginx/1.24.0 (Ubuntu)

主配置末尾 include:/etc/nginx/conf.d/*.conf 和 /etc/nginx/sites-enabled/*。

4.2 站点 1:Hexo 博客(8080)

server {
listen 0.0.0.0:8080;
server_name blog.nesthub.dpdns.org;

root /var/www/blog-nesthub;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

location ~* \.(jpg|jpeg|png|gif|webp|svg|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}

4.3 站点 2:图片画廊(8081)

server {
listen 0.0.0.0:8081;
server_name localhost;

root /var/www/image-gallery;
index index.html;

location / { try_files $uri $uri/ /index.html; }

location /uploads/ {
alias /var/www/image-gallery/uploads/;
expires 30d;
add_header Cache-Control "public, no-transform";
}

location ~* \.(jpg|jpeg|png|gif|webp|svg|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}

4.4 站点 3:SearXNG 反向代理(8083)

server {
listen 0.0.0.0:8083;
server_name localhost;

location / {
proxy_pass http://127.0.0.1:9090;
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_buffering off;
proxy_request_buffering off;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}

proxy_buffering off 是因为 SearXNG 是流式/长轮询接口,关闭缓冲避免结果延迟。

4.5 站点 4:OALD10 词典(8099)

server {
listen 0.0.0.0:8099;
server_name localhost;
charset utf-8;

location = / { root /root/oald10; try_files /index.html =404; }
location = /styles.css { root /root/oald10; add_header Cache-Control "public, max-age=3600"; }

location ~ ^/yomitan-css/([a-zA-Z0-9_-]+\.css)$ {
alias /root/oald10/yomitan-css/$1;
default_type text/css;
add_header Cache-Control "public, max-age=3600";
}

location /api/ {
proxy_pass http://127.0.0.1:12700;
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_connect_timeout 5s;
proxy_read_timeout 30s;
}

location / { return 404; } # 关键:禁止直接读 server.py / oald10.db
}

4.6 sites-available / sites-enabled 机制

sites-available 存所有站点配置,sites-enabled 存实际启用的站点(Nginx 只读此目录),两者靠软链接关联:

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/   # 启用
rm /etc/nginx/sites-enabled/example.com # 禁用
nginx -t && nginx -s reload # 校验并重载

4.7 无 systemd 环境下的 Nginx 管理

nginx                          # 启动
service nginx start # 或 SysV 脚本
nginx -g "daemon on;" # 后台常驻(容器专用)
pkill nginx # 关闭所有进程(无 systemctl)
nginx -s reload / stop
nginx -t # 语法检查

4.8 Nginx 500 报错排错

日志报 rewrite or internal redirection cycle while internally redirecting to "/index.html",三个原因:root 目录配置错误(旧指向 /var/www/hexo-blog,实际 /var/www/blog-nesthub)、容器无法监听 80/443、无 systemctl。解决:修正 root 路径、规范 try_files、index 写在 server 层级,并执行:

chown -R www-data:www-data /var/www/blog-nesthub

5. Hexo 博客部署与自动化运维

5.1 架构

  • 源码仓库:Gitee 私有仓库(分支 main)
  • 编译工具链:Node.js + pnpm + Hexo
  • 产物目录:/var/www/blog-nesthub(nginx root)
  • 多配置编译:hexo generate --config _config.yml,_config.nesthub.yml 双配置合并

5.2 部署流程(deploy-blog.sh,一键 4 步)

cd /root/zzcblog-source
git pull origin main # 1. 拉最新源码
pnpm install # 2. 按需装依赖
hexo clean && hexo generate --config _config.yml,_config.nesthub.yml # 3. 编译
nginx -s reload # 4. 重载

脚本完整流程:

[1/4] 更新源码:git fetch + checkout + pull(无 stash,保持干净工作区)
[2/4] 依赖:检测 package.json / pnpm-lock.yaml 的 md5,变化才 pnpm install
[3/4] 编译:hexo clean && generate → 校验 public/index.html 存在 → 原子替换(.new → .old → mv)
[4/4] nginx:nginx -t 校验 → 平滑 reload

5.3 亮点设计

  1. 并发锁:flock 锁 /tmp/deploy-blog.lock;
  2. 原子发布:先复制到 .new 再 mv 切换,避免半成品页面;
  3. 依赖指纹:md5 判断依赖是否变更;
  4. DNS 自愈:ping 不通阿里云就重写 resolv.conf(223.5.5.5 / 114.114.114.114);
  5. 错误捕获:trap ERR 记录失败行号,trap EXIT 写结束日志;
  6. 日志:/var/log/deploy-blog.log。

5.4 原脚本隐患修正

  1. chown -R root:root 导致 Nginx(www-data)读权限不足 → 改为 chown -R www-data:www-data "$TMP_WEB";
  2. 危险 git stash 逻辑 → 改为无 stash 的 fetch+checkout+pull;
  3. 缺并发锁 → 加 flock。

5.5 访问与常见报错

访问 http://blog.nesthub.dpdns.org:8080(无证书,https 暂不可用)。

报错 原因 解决
bind() to 0.0.0.0:80 failed (13: Permission denied) proot 容器限制 改用 8080 高端口
System has not been booted with systemd 无 systemd 用 pkill nginx 管理进程
rewrite 重定向循环 500 root 路径错误 修正 root、规范 try_files

6. MinIO 对象存储与图床

6.1 安装(ARM64 / 国内镜像)

wget https://dl.minio.org.cn/server/minio/release/linux-arm64/minio -O /usr/local/bin/minio
chmod +x /usr/local/bin/minio

6.2 启动参数

export MINIO_ROOT_USER="<用户名>"
export MINIO_ROOT_PASSWORD="<密码>"
export MINIO_SERVER_URL="https://img.nesthub.dpdns.org" # ★ 声明公网域名
minio server /data/minio --console-address :9001 --address :9000

端口:9000 API / 9001 控制台。MINIO_SERVER_URL 必须设为公网域名,否则预签名 URL 指向内网 IP。

6.3 mc 客户端与匿名权限

从 2024 年新版本起,网页端「设置公开访问」按钮被删除,只能用命令行 mc 改匿名权限。

curl https://dl.minio.org.cn/client/mc/release/linux-arm64/mc -o /usr/local/bin/mc
chmod +x /usr/local/bin/mc
mc alias set --insecure myminio http://127.0.0.1:9000 <用户名> <密码>

mc mb myminio/bedimg # 建桶
mc anonymous set off myminio/bedimg # 私有(默认)
mc anonymous set download myminio/bedimg # 公开只读(图床推荐)
mc anonymous set public myminio/bedimg # 完全公开
mc anonymous get myminio/bedimg # 查看权限

6.4 健康检查

curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9000   # 403 正常(无 bucket 时)
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9001 # 200

MinIO 根路径返回 403 是正常行为,不要误判为故障。

6.5 Cloudflare Tunnel + 图床(公网方案)

架构:PicGo → HTTPS → Cloudflare Edge → cloudflared → MinIO(9000/9001)。

安装并创建隧道:

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64
mv cloudflared-linux-arm64 /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared
cloudflared tunnel login
cloudflared tunnel create my-minio

配置 ~/.cloudflared/config.yml:

tunnel: <隧道 UUID>
credentials-file: /root/.cloudflared/<UUID>.json
protocol: http2 # 强制 HTTP/2,避免 QUIC 被运营商干扰

ingress:
- hostname: minio.nesthub.dpdns.org
service: https://127.0.0.1:9000
originRequest:
httpHostHeader: minio.nesthub.dpdns.org
noTLSVerify: true
httpHeaders:
Accept-Encoding: identity # 防签名失败
- hostname: console.nesthub.dpdns.org
service: https://127.0.0.1:9001
originRequest:
httpHostHeader: console.nesthub.dpdns.org
noTLSVerify: true
httpHeaders:
Accept-Encoding: identity
- service: http_status:404

DNS 加两条 CNAME 指向 .cfargotunnel.com(代理开启橙色云),并给两个域名配置 Bypass cache 缓存规则。

PicGo 接入用专用用户(不要用 root):

mc admin user add myminio picgo <密码>
mc admin policy attach myminio readwrite --user=picgo
mc anonymous set download myminio/test

PicGo 字段:EndPoint minio.nesthub.dpdns.org(不含 https://)、UseSSL 勾选、AccessKey picgo、Bucket test;S3 插件需勾选 Path style。

6.6 常见坑点速查

问题 根因 解决
控制台资源加载失败 9000/9001 分离 双子域名 + ingress 分别路由
Tunnel 连不上 QUIC 被干扰 protocol: http2
PicGo AccessDenied 无 s3:PutObject 附加 readwrite 策略
PicGo SignatureDoesNotMatch Cloudflare 改写头 Accept-Encoding: identity
Region 不匹配 插件硬编码 us-east-1 MINIO_REGION_NAME="us-east-1"
图片直链 403 匿名无读取权限 mc anonymous set download

7. SearXNG 元搜索引擎

7.1 源码 + venv 安装

git clone https://github.com/searxng/searxng.git /root/searxng
cd /root/searxng
python3 -m venv venv
./venv/bin/pip install -U pip setuptools wheel
./venv/bin/pip install -e .

运行入口 /root/searxng/venv/bin/python -m searx.webapp,配置文件 /etc/searxng/settings.yml。

7.2 关键配置

server:
secret_key: "<随机密钥>"
bind_address: "127.0.0.1" # 只监听回环,靠 nginx 反代
port: 9090
image_proxy: true # 图片代理,避免防盗链

ui:
theme: simple
default_locale: "zh-Hans-CN"

search:
autocomplete: "bing"
default_lang: "zh-CN"
limiter: false # 单用户自用,关闭限流

7.3 启动脚本与 Nginx 反代

/root/scripts/searxng.sh 支持 start|stop|restart|status,环境变量 SEARXNG_SETTINGS_PATH、PYTHONPATH=/root/searxng,PID /root/scripts/pids/searxng.pid,日志 /root/scripts/logs/searxng.log。

Nginx 反代(8083 → 127.0.0.1:9090)见第四章 4.4 节,核心是 proxy_buffering off。


8. OALD10 网页词典

基于牛津高阶英汉双解词典第 10 版(OALD10)的自建查词服务,零依赖纯标准库实现,适配 Yomitan 样式。

8.1 目录与数据

/root/oald10/
├── server.py # Python 后端(仅标准库,~16KB)
├── oald10.db # SQLite 词典库(约 400MB,zlib 压缩词条)
├── index.html # 前端页面
├── styles.css # oald 定制样式
├── yomitan-css/ # Yomitan 样式表
├── nginx-oald10.conf # nginx 站点配置
└── start-oald10.sh # 启动脚本

8.2 后端接口(server.py,监听 12700)

接口 说明
GET /api/lookup?w=WORD 精确查词(重定向/多词性聚合/拼写建议)
GET /api/search?q=TEXT&n=20 全文搜索(英文 FTS5 / 中文 LIKE,offset 分页)
GET /api/prefix?p=PREF&n=30 词头前缀匹配
GET /api/random 随机返回一个主词条

启动:python3 server.py --host 127.0.0.1 --port 12700。

8.3 Nginx 安全反代

安全设计(配置见 4.5 节):静态资源 nginx 直服、/api/* 反代到 12700、默认 location / { return 404; } 堵死源码/数据库下载路径、yomitan-css 正则白名单。


9. Alist 文件云盘

9.1 安装

mkdir -p /opt/alist
# 下载 alist 二进制(arm64)到 /opt/alist/alist
chmod +x /opt/alist/alist
/opt/alist/alist server # 首次运行初始化

数据目录 /opt/alist/data/(config.json + data.db + log),端口 HTTP 5244 / FTP 5246。

9.2 配置与启动

{
"scheme": { "address": "0.0.0.0", "http_port": 5244, "https_port": -1, "force_https": false },
"database": { "type": "sqlite3", "db_file": "data/data.db", "table_prefix": "x_" }
}
# /root/scripts/start_alist.sh
nohup alist server > /root/scripts/logs/alist.log 2>&1 &

脚本依赖 PATH 里的 alist 命令,也可用绝对路径 /opt/alist/alist server。默认仅局域网访问。


10. 内网穿透与远程访问

10.1 frp(博客域名 → 8080)

架构:浏览器 → blog.nesthub.dpdns.org → frp 服务端 → frpc → 127.0.0.1:8080 → nginx → Hexo。

隧道配置 /root/frp/nginx.ini:

[common]
server_addr = <服务端地址>
server_port = 7000
tls_enable = false
user = <用户>
token = <令牌>

[N7V9QmG1]
type = http
local_ip = 127.0.0.1
local_port = 8080
custom_domains = blog.nesthub.dpdns.org

启动与停止:

nohup /root/frp/frpc -c /root/frp/nginx.ini >> /var/log/frpc-nginx.log 2>&1 &
echo $! > /var/run/frpc-nginx.pid
/root/scripts/stop-frpc.sh nginx

经验:日志持续报 connection refused,说明 frpc 活着但后端端口没监听,要 curl 检查后端。

10.2 cloudflared(图床 → Cloudflare CDN)

命名隧道配置 /root/scripts/tunnel-named.yml:

tunnel: <隧道 UUID>
credentials-file: /root/.cloudflared/<UUID>.json

ingress:
- hostname: img.nesthub.dpdns.org
service: http://127.0.0.1:9000
originRequest:
enableCompression: true # 只允许写在单条域名规则下
connectTimeout: 60s
tcpKeepAlive: 30s
- service: http_status:404

启动(关键参数):

cloudflared tunnel --config /root/scripts/tunnel-named.yml \
--protocol http2 --edge-ip-version 4 --no-prechecks --ha-connections 6 run blog-tunnel

10.3 Tailscale(私有组网 + 远程管理)

proot 容器无法创建 TUN 设备,必须用 userspace 模式:

curl -fsSL https://tailscale.com/install.sh | sh

mkdir -p /run/tailscale /var/lib/tailscale
tailscaled --tun=userspace-networking \
--socket=/run/tailscale/tailscaled.sock \
--statedir=/var/lib/tailscale \
--port=41641 \
--socks5-server=localhost:1055 \
--outbound-http-proxy-listen=localhost:1055 \
> /var/log/tailscaled.log 2>&1 &

tailscale --socket=/run/tailscale/tailscaled.sock up

userspace 模式需用 tailscale serve 显式转发端口:

tailscale --socket=/run/tailscale/tailscaled.sock serve tcp:8080:localhost:8080
tailscale --socket=/run/tailscale/tailscaled.sock serve status
tailscale --socket=/run/tailscale/tailscaled.sock serve reset

更推荐:Android 宿主直接装 Tailscale App(TUN 模式),有虚拟网卡、自动路由、内核态性能,容器内监听 0.0.0.0 的服务自动暴露。

Windows 同时跑 FlClash + Tailscale,需在 FlClash TUN 排除 Tailscale 网段:

tun:
enable: true
route-exclude-address:
- 100.64.0.0/10
- 100.100.100.100/32
- fd7a:115c:a1e0::/48

Tailscale 快的原因:WireGuard 加密 + 设备间 P2P 直连(Direct 直连延迟最低、吞吐最高;DERP 中继国内较慢)。提速方案:路由器放行 UDP 41641、自建 DERP 中继、配置 Peer Relay。

10.4 三种方案定位

方案 适用场景 公网域名
frp 博客等 HTTP 服务对外 blog → 8080
cloudflared 图床走 CDN img → 9000
Tailscale 私有组网、远程管理 无公网域名,P2P

11. mihomo 科学上网代理

11.1 端口配置

项 值
mixed-port 7890(HTTP/SOCKS5 混合)
allow-lan true
mode rule
external-controller 0.0.0.0:9097(避开 SearXNG 的 9090)
external-ui /etc/mihomo/ui
DNS listen 127.0.0.1:1053(fake-ip)

11.2 终端代理开关(proxy.sh)

由 .bashrc source 引入,用函数改当前终端环境变量:

proxy on / off / status

no_proxy 配置:

PROXY_NO_PROXY="localhost,127.0.0.1,::1,192.168.5.85,nesthub.dpdns.org"

⚠️ curl 的 no_proxy 不支持 *.domain 通配,裸域名已匹配所有子域名,不要加星号。

11.3 订阅自动更新

每天 04:40 cron 触发:curl 下载订阅(UA 伪装 clash.meta)→ 校验含 proxies: → sed 注入 external-controller 9097 等修正 → mihomo -d /etc/mihomo -t 语法校验 → 通过才覆盖并重启。日志 /var/log/mihomo/sub-update.log。


12. MySQL / MariaDB 数据库

12.1 安装与启动(绕过 systemd)

apt install -y mariadb-server     # 推荐 MariaDB(约 200-250MB 内存)

# MariaDB 启动
service mariadb start

# MySQL 8.0 手动方式
mkdir -p /run/mysqld && chown mysql:mysql /run/mysqld
mysqld --initialize-insecure --user=mysql 2>/dev/null || true
nohup mysqld --user=mysql --datadir=/var/lib/mysql > /var/log/mysql.log 2>&1 &

12.2 安全初始化与建库

mysql_secure_installation    # 设 root 密码、移除匿名用户、禁远程 root、删 test 库
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myuser'@'%' IDENTIFIED BY '密码';
GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%';
FLUSH PRIVILEGES;

12.3 远程访问与自启

编辑 50-server.cnf 设 bind-address = 0.0.0.0,重启后 mysql -u myuser -p -h 192.168.x.x 测试。

cat > /etc/profile.d/mysql.sh <<'EOF'
#!/bin/sh
if ! pgrep -x "mariadbd" > /dev/null; then
mkdir -p /run/mysqld
chown mysql:mysql /run/mysqld
nohup mysqld --user=mysql --datadir=/var/lib/mysql > /var/log/mysql.log 2>&1 &
fi
EOF
chmod +x /etc/profile.d/mysql.sh

12.4 现实约束

项目 说明
内存占用 MariaDB ~200-250MB,MySQL ~350-400MB
性能 proot I/O 开销大,不适合高并发
保活 锁屏可能被杀,需 termux-wake-lock
适用场景 开发测试、小型应用后端,不推荐生产

13. 服务管理脚本体系与故障排查

13.1 脚本总目录

所有脚本集中在 /root/scripts/,是这套服务器的运维入口:

脚本 作用
manage-services.sh 统一管理 nginx + MinIO + frpc
start-all.sh 一键启动 nginx + MinIO + SearXNG
start-minio.sh MinIO 管理(start/stop/restart/status/logs)
searxng.sh / mihomo.sh 各自服务管理
proxy.sh 终端代理开关
update-mihomo-sub.sh 订阅自动更新
start_alist.sh / start-oald10.sh 服务启动
deploy-blog.sh / git_pull.sh 博客部署
cf-auto-run.sh / cf-named-start.sh / cf-stop.sh cloudflared 管理
stop-frpc.sh 停止 frpc 实例

13.2 统一管理脚本(manage-services.sh)

INSTANCES=("nginx") 数组声明 frpc 实例,扩展新隧道加元素即可。start_frpc_instance() 检查配置 → 防重复 → nohup 启动 → 写 pid → 验证存活;stop_frpc_instance() 读 pid → kill → kill -9 兜底 → 清理 pid。

13.3 通用服务脚本模板

任何需手动启动的服务都能套用(set -euo pipefail + 五子命令 + 防重复 + 优雅停止 + 彩色日志)。极简版:

#!/bin/sh
if ! pgrep -x "<服务进程名>" > /dev/null; then
mkdir -p /run/<服务名>
nohup <启动命令> > /var/log/<服务名>.log 2>&1 &
fi

13.4 PID / 日志约定

统一路径避免混乱:MinIO /var/run/minio.pid、frpc /var/run/frpc-<name>.pid、SearXNG /root/scripts/pids/searxng.pid、mihomo /root/scripts/pids/mihomo.pid、cloudflared /root/scripts/pids/cf-tunnel.pid、OALD10 /root/oald10/server.pid。

13.5 定时任务(cron)

# 每天 05:38 acme.sh 证书续期
# 每天 04:40 update-mihomo-sub.sh 更新订阅

13.6 运维速查

健康检查统一用 curl + pgrep(proot 下 ss/netstat/lsof 不可用):

curl -s -o /dev/null -w "nginx8080=%{http_code}\n" http://127.0.0.1:8080
curl -s -o /dev/null -w "searx9090=%{http_code}\n" http://127.0.0.1:9090
curl -s -o /dev/null -w "minio9000=%{http_code}\n" http://127.0.0.1:9000

13.7 故障排查经验集

① 僵尸在线:pgrep -x minio 有 PID 但端口全拒、日志 0 字节。排查 ps aux | grep minio 看 STAT 是否 S/D、数 socket fd、curl 实测端口。根因是进程异常沉睡未完成端口绑定,start-minio.sh restart 解决。教训:进程存在 ≠ 服务正常,必须用 curl 做健康检查。

② frpc 隧道不通:依次查进程 → 日志 → 后端端口 curl → pid 文件是否残留。常见根因:后端没起来、pid 残留导致脚本跳过启动、域名配置不对。

③ 端口探测手法:curl -s -o /dev/null --max-time 2 -w "%{http_code}" http://127.0.0.1:PORT + pgrep -x 服务名。

④ no_proxy 通配坑:不支持 *.domain,裸域名已匹配子域名,不要加星号。

⑤ 端口冲突:mihomo external-controller 从 9090 改 9097 避开 SearXNG,新增服务先查端口表。

⑥ MinIO 预签名 URL 指向内网:必须设 MINIO_SERVER_URL 为公网域名。

13.8 端口规划总表

端口 服务 绑定 用途
8080 nginx 0.0.0.0 Hexo 博客
8081 nginx 0.0.0.0 图片画廊
8083 nginx 0.0.0.0 SearXNG 反代
8099 nginx 0.0.0.0 OALD10 词典
9090 SearXNG 127.0.0.1 搜索引擎本体
12700 OALD10 127.0.0.1 词典 API
5244/5246 Alist 0.0.0.0 网盘 HTTP/FTP
9000/9001 MinIO 0.0.0.0 API / 控制台
7890 mihomo 0.0.0.0 混合代理
9097 mihomo 0.0.0.0 Web 面板
1053 mihomo 127.0.0.1 DNS
7000 frpc - 连接 frp 服务端

结语

一台手机从「能跑 Linux」到「承载十几个服务的家庭服务器」,关键不在某个单独的工具,而在一套连贯的方法:用 Termux + proot 搭出环境,用 Nginx 做统一网关,用脚本体系替代 systemd 做服务管理,用 frp/cloudflared/Tailscale 解决公网访问,最后用「进程活着 ≠ 服务正常」这类经验守住稳定性。本文覆盖的每一条命令和配置都来自实际运行环境,可直接对应真实文件,供按需取用和二次修改。


本文基于 Termux + proot-distro Ubuntu 环境整理,源文件中的明文密码、token、secret、隧道 UUID 等凭据已脱敏为占位符。