笨猫博客

  • 🍟首页
  • 🍘目录
    • 🥝VPS教程
    • 🍾猫玩技术
    • 🍹干货分享
    • 🍏软件分享
    • 🍩一只猫
  • 🍋工具
    • 🌽IP路由追踪
    • 🍐域名Whois查询
    • 🥘域名被墙查询
    • 🍧IP正常检测
    • 🔥IP端口检测
    • 🍆短网址
    • 🐟VIP音乐播放
    • 🍯KMS激活
  • 🍓链接
  • 🍪联系
  • 🍱登录
    • 🥦登录
    • 🍒注册
关注互联网,生活,音乐,乐此不疲的一只笨猫
  1. 首页
  2. 猫玩技术
  3. 正文

Docker 自托管 Shlink 短链服务

2026-01-22 3点热度 0人点赞 0条评论

引言

Shlink 是一款基于 PHP 的自托管网址缩短服务。由于个人对 PHP 存在一定心理门槛😅,此前一直未尝试部署。近期阅读项目文档后发现,它实际上支持多种 PHP Runtime(运行时):

  • RoadRunner
  • FrankenPHP
  • 传统方式(Web Server + FastCGI)

其中,RoadRunner 是 Shlink 官方推荐的默认运行方式。它是一款由 Go 编写的 PHP 运行时,通过多个 Worker 将 Shlink 常驻于内存 (RAM) 中运行,在响应速度和整体性能方面表现良好。

部署 Shlink

Shlink 后端服务与 Web 管理后台是分离的,Web 管理面板有两种解决方案:

  • shlink-web-client :官方提供的 PWA Web 应用,纯静态应用,API Key 存储在浏览器的本地存储中
  • shlink-dashboard :官方的下一代 Web 面板,包含 shlink-web-client 的所有功能,并支持高级用户认证和角色管理,API Key 统一存储在服务器端。

我选择 shlink-dashboard 作为 Web 管理面板,并使用 PostgreSQL 作为后端服务与管理面板共用的数据库。

准备 Docker 模板

新建 compose.yml 模板,写入

services:
  db:
    image: postgres:18-alpine
    container_name: shlink-db
    restart: unless-stopped
    environment:
      - POSTGRES_DB=shlink        # Shlink 数据库名称
      - POSTGRES_USER=shlink      # 数据库用户名
      - POSTGRES_PASSWORD=shlink  # 数据库密码
    volumes:
      - ./data:/var/lib/postgresql
      - ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql:ro  # 初始化阶段创建另一个数据库
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U shlink -d shlink"]
      interval: 10s
      timeout: 5s
      retries: 5

  shlink-backend:
    image: shlinkio/shlink:stable
    container_name: shlink-backend
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DB_DRIVER=postgres
      - DB_HOST=db
      - DB_NAME=shlink              # Shlink 数据库名称
      - DB_USER=shlink              # 数据库用户名
      - DB_PASSWORD=shlink          # 数据库密码
      - DEFAULT_DOMAIN=your.domain  # 要绑定的短链接域名
      - IS_HTTPS_ENABLED=true       # 启用 HTTPS
      - TIMEZONE=Asia/Shanghai
      - GEOLITE_LICENSE_KEY=        # [可选] MaxMind GeoLite Key
      - TRUSTED_PROXIES=172.16.0.0/12
      - LOGS_FORMAT=json
      - DEFAULT_SHORT_CODES_LENGTH=4
      - SHORT_URL_TRAILING_SLASH=true
    ports:
      - '127.0.0.1:8080:8080'
  
  shlink-web:
    image: shlinkio/shlink-dashboard:stable
    container_name: shlink-web
    user: '1000:1000'
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
     - '127.0.0.1:3005:3005'
    environment:
      SHLINK_DASHBOARD_DB_DRIVER: postgres
      SHLINK_DASHBOARD_DB_HOST: db
      SHLINK_DASHBOARD_DB_PORT: 5432
      SHLINK_DASHBOARD_DB_NAME: dashboard   # shlink-dashboard 数据库名称
      SHLINK_DASHBOARD_DB_USER: shlink      # 数据库用户名
      SHLINK_DASHBOARD_DB_PASSWORD: shlink  # 数据库密码
      SHLINK_DASHBOARD_SESSION_SECRETS: secret1,secret2...  # 修改会话机密,设置多个高强度随机值,半角逗号隔开

Shlink 与 shlink-dashboard 将共用同一个 PostgreSQL 容器。由于该镜像在初始化阶段默认仅创建单一数据库,我们的预期是分别为两者提供独立的数据库。

准备一个 init-db.sql,并在其中定义相应的初始化逻辑,这会在 PostgreSQL 首次启动时执行并最终创建两个可用的数据库。

CREATE DATABASE dashboard;

启动服务

似乎没有必要,但为了稳妥起见,先启动数据库

sudo docker compose up -d db

低配置的 VPS 建议手动检查健康状况,确保数据库准备就绪

sudo docker compose ps db
# 或者
sudo docker compose logs -f db

现在可以启动所有服务

sudo sudo docker compose up -d

生成访问凭据

使用 Shlink CLI 工具生成访问密钥,用于后续 Web 管理面板添加服务器

sudo docker exec -it shlink-backend shlink api-key:generate

看起来是 UUID 格式,复制保留备用

gen-api-key.webp

[附] Shlink CLI 命令手册建议保留备用

用法:
  command [options] [arguments]

选项:
  -h, --help            显示指定命令的帮助信息;如果未指定命令,则显示命令列表的帮助
      --silent          不输出任何信息
  -q, --quiet           仅显示错误信息,其他所有输出都会被抑制
  -V, --version         显示当前应用程序的版本
      --ansi|--no-ansi  强制启用(或禁用)ANSI 输出
  -n, --no-interaction  不询问任何交互式问题
  -v|vv|vvv, --verbose  提高输出详细程度:1 为普通输出,2 为更详细输出,3 为调试输出

可用命令:
  completion                      输出 shell 自动补全脚本
  help                            显示某个命令的帮助信息
  list                            列出所有可用命令
 api-key
  api-key:delete                  按名称删除一个 API Key
  api-key:disable                 按名称或明文 key 禁用一个 API Key(使用明文 key 的方式已被弃用)
  api-key:generate                生成一个新的有效 API Key
  api-key:initial                 尝试创建初始 API Key
  api-key:list                    列出所有可用的 API Key
  api-key:rename                  按名称重命名一个 API Key
 domain
  domain:list                     列出曾被用于任意短链接的所有域名
  domain:redirects                为指定域名设置特定的“未找到(404)”重定向规则
  domain:visits                   返回指定域名的访问记录列表
 integration
  integration:matomo:send-visits  将现有访问记录发送到已配置的 Matomo 实例
 short-url
  short-url:create                为提供的长链接生成一个短链接并返回
  short-url:delete                删除一个短链接
  short-url:delete-expired        删除所有被视为已过期的短链接(有效时间早于当前时间)
  short-url:edit                  编辑一个已有的短链接
  short-url:import                允许从第三方来源导入短链接
  short-url:list                  列出所有短链接
  short-url:manage-rules          为某个短链接设置重定向规则
  short-url:parse                 返回某个短代码对应的原始长链接
  short-url:visits                返回指定短代码的详细访问记录信息
  short-url:visits-delete         删除某个短链接的访问记录
 tag
  tag:delete                      删除一个或多个标签
  tag:list                        列出现有的标签
  tag:rename                      重命名一个已有的标签
  tag:visits                      返回指定标签的访问记录列表
 visit
  visit:download-db               检查 GeoLite2 数据库文件是否过旧或不存在,如是则尝试下载最新版本
  visit:locate                    解析访问记录的来源地理位置;如有需要会自动下载或更新 GeoLite2 数据库
  visit:non-orphan                返回非孤立访问记录的列表
  visit:orphan                    返回孤立访问记录的列表
  visit:orphan-delete             删除所有孤立访问记录

设置反向代理

为了方便管理,我将 Shlink 和 shlink-dashboard 放到同一个 Nginx 虚拟主机反向代理配置内:

server {
    listen 80;
    listen [::]:80;
    server_name your.domain shlink-dash.your.domain;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name your.domain;

    ssl_certificate /path/to/cert/your.domain.pem;
    ssl_certificate_key /path/to/cert/your.domain.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ecdh_curve X25519:P-256:P-384;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256';
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    access_log /var/log/nginx/your.domain.access.log;
    error_log /var/log/nginx/your.domain.error.log;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;

        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $realip_remote_addr;
        proxy_set_header X-Forwarded-Proto https;

        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 90s;

        proxy_redirect off;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name shlink-dash.your.domain;

    ssl_certificate /path/to/cert/shlink-dash.your.domain.pem;
    ssl_certificate_key /path/to/cert/shlink-dash.your.domain.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ecdh_curve X25519:P-256:P-384;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256';
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    access_log /var/log/nginx/shlink-dash.your.domain.access.log;
    error_log /var/log/nginx/shlink-dash.your.domain.error.log;

    location / {
        proxy_pass http://127.0.0.1:3005;
        proxy_http_version 1.1;

        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $realip_remote_addr;
        proxy_set_header X-Forwarded-Proto https;

        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 60s;

        proxy_redirect off;

        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "no-referrer-when-downgrade" always;
        add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    }
}

检查 Nginx 配置

sudo nginx -t

重载 Nginx 配置

sudo nginx -s reload

使用服务

登录管理后台

访问 shlink-dash.your.domain 面板,默认用户名和密码都是 admin,登录后会要求修改密码。

login.webp

添加服务器

重置密码后就进入管理后台了,点击添加服务器

add-server.webp

输入服务器信息和访问凭据即可

add-new-server.webp

现在就可以愉快的使用了。

enjoy.webp

标签: 暂无
最后更新:2026-01-13

笨猫

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

最新 热点 随机
最新 热点 随机
Docker 自托管 Shlink 短链服务 Linux BBR V3 管理脚本:支持arm和x86-64轻松加速网络,让服务器飞起来! 船新的PT刷流脚本,傻瓜式一键部署好完整刷流环境VT+QB439+Filebrowser+系统优化 EnsoAI:让多个 Agents 并行开发 [多路智能|并行穿梭] 开源输入法:支持跨设备剪贴板同步与验证码提取 炸酱面探针在线演示及安装教程(测试)
开源输入法:支持跨设备剪贴板同步与验证码提取EnsoAI:让多个 Agents 并行开发 [多路智能|并行穿梭]船新的PT刷流脚本,傻瓜式一键部署好完整刷流环境VT+QB439+Filebrowser+系统优化Linux BBR V3 管理脚本:支持arm和x86-64轻松加速网络,让服务器飞起来!Docker 自托管 Shlink 短链服务
dangliu攻击本人事件 WIN10自带计算器和应用商店打不开-解决办法 免费索取 Ubuntu 8.10光盘 Fix8联手娜娜米米推出娱乐视频服务 《复仇者联盟4:终局之战》HD高清版提前流出(外挂字幕) Netflix检测脚本合集,一键检测IP解锁范围及 对应的的地区
最近评论
vioulo 发布于 2 周前(01月07日) 之前以为 fcitx5 只能再 linux 上用来的 :smile:
dk 发布于 4 个月前(09月22日) 哈哈哈哈
天天下载Ttzip 发布于 4 个月前(09月15日) 很棒的网站!感谢分享,谢谢站长!!@天天下载Ttzip
诗音 发布于 5 个月前(08月29日) 时间改到2099年在暂停更新也可以
vip券网 发布于 6 个月前(08月01日) 写的很详细,赞 :razz: :evil:
标签
elliptictrue100.10.02
BLOG ChatGPT Chrome CloudFlare DirectAdmin github Godaddy google kloxo Linux OneDrive OneIndex PHP QQ shadowsocks SNS ssh Typecho VPS web2.0 whmcs Windows wordpress 一键脚本 下载 免费 博客 图文教程 图标 图片 域名 头像 奥运 宝塔面板 插件 教程 日记 有趣 浏览器 游戏 猫 生活 电影 百度 网站 视频 设计 软件 阿里云盘 音乐
好友
  • glzjin's blog glzjin's blog
  • ZAERA博客
  • 冰沫记
  • 奇它博客
  • 猫腻‘s Blog
  • 猫饭
  • 肥宅之家
  • 萌博
  • 野路子程序员

COPYRIGHT © 2022 笨猫博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang