Linux 上使用 Docker 安装,Windows 上使用 alist start 启动,默认端口号为 5244

更新密码

alist admin set 12345678

挂载百度网盘

默认采用 302 重定向,但需要在客户端浏览器添加 user-agent: pan.baidu.com

挂载本地存储

如果需要缩略图展示,则需要设置 ffmpeg 到环境变量

使用代理URL访问百度网盘

由于需要保证高带宽的代理环境,不能直接使用 VPS ,容易被封。

推荐使用 cloudflare 的 worker 云函数:科赋锐信息科技Cloudflare

准备工作

  1. 一个 VPS 服务器。
  2. 一个 cloudflare 账号。
  3. 一个域名,使用 cloudflare 管理。

在 cloudflare 中创建 worker,编辑代码

// src/const.ts
var ADDRESS = "http://alist.tph.fan";
var TOKEN = "********";
var WORKER_ADDRESS = "http://alist_proxy.tph.fan";
 
// src/verify.ts
var verify = async (data, _sign) => {
  const signSlice = _sign.split(":");
  if (!signSlice[signSlice.length - 1]) {
    return "expire missing";
  }
  const expire = parseInt(signSlice[signSlice.length - 1]);
  if (isNaN(expire)) {
    return "expire invalid";
  }
  if (expire < Date.now() / 1e3 && expire > 0) {
    return "expire expired";
  }
  const right = await hmacSha256Sign(data, expire);
  if (_sign !== right) {
    return "sign mismatch";
  }
  return "";
};
var hmacSha256Sign = async (data, expire) => {
  const key = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(TOKEN),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign", "verify"]
  );
  const buf = await crypto.subtle.sign(
    {
      name: "HMAC",
      hash: "SHA-256"
    },
    key,
    new TextEncoder().encode(`${data}:${expire}`)
  );
  return btoa(String.fromCharCode(...new Uint8Array(buf))).replace(/\+/g, "-").replace(/\//g, "_") + ":" + expire;
};
 
// src/handleDownload.ts
async function handleDownload(request) {
  const origin = request.headers.get("origin") ?? "*";
  const url = new URL(request.url);
  const path = decodeURIComponent(url.pathname);
  const sign = url.searchParams.get("sign") ?? "";
  const verifyResult = await verify(path, sign);
  if (verifyResult !== "") {
    const resp2 = new Response(
      JSON.stringify({
        code: 401,
        message: verifyResult
      }),
      {
        headers: {
          "content-type": "application/json;charset=UTF-8"
        }
      }
    );
    resp2.headers.set("Access-Control-Allow-Origin", origin);
    return resp2;
  }
  let resp = await fetch(`${ADDRESS}/api/fs/link`, {
    method: "POST",
    headers: {
      "content-type": "application/json;charset=UTF-8",
      Authorization: TOKEN
    },
    body: JSON.stringify({
      path
    })
  });
  let res = await resp.json();
  if (res.code !== 200) {
    return new Response(JSON.stringify(res));
  }
  request = new Request(res.data.url, {
    ...request,
    headers: new Headers([
      ...Array.from(request.headers.entries()),
      ["User-Agent", "pan.baidu.com"]
    ])
  });
  if (res.data.header) {
    for (const k in res.data.header) {
      for (const v of res.data.header[k]) {
        request.headers.set(k, v);
      }
    }
  }
  let response = await fetch(request);
  while (response.status >= 300 && response.status < 400) {
    const location = response.headers.get("Location");
    if (location) {
      if (location.startsWith(`${WORKER_ADDRESS}/`)) {
        request = new Request(location, request);
        return await handleRequest(request);
      } else {
        request = new Request(location, request);
        response = await fetch(request);
      }
    } else {
      break;
    }
  }
  response = new Response(response.body, response);
  response.headers.delete("set-cookie");
  response.headers.set("Access-Control-Allow-Origin", origin);
  response.headers.append("Vary", "Origin");
  return response;
}
 
// src/handleOptions.ts
function handleOptions(request) {
  const corsHeaders = {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
    "Access-Control-Max-Age": "86400"
  };
  let headers = request.headers;
  if (headers.get("Origin") !== null && headers.get("Access-Control-Request-Method") !== null) {
    let respHeaders = {
      ...corsHeaders,
      "Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers") || ""
    };
    return new Response(null, {
      headers: respHeaders
    });
  } else {
    return new Response(null, {
      headers: {
        Allow: "GET, HEAD, POST, OPTIONS"
      }
    });
  }
}
 
// src/handleRequest.ts
async function handleRequest(request) {
  if (request.method === "OPTIONS") {
    return handleOptions(request);
  }
  return await handleDownload(request);
}
 
// src/index.ts
var src_default = {
  async fetch(request, env, ctx) {
    return await handleRequest(request);
  }
};
export {
  src_default as default
};
//# sourceMappingURL=index.js.map

需设置三个参数:

  1. ADDRESS:alist 服务器地址
  2. TOKEN:${ADDRESS}/@manage/settings/other中的令牌
  3. WORKER_ADDRESS:alist 代理地址

添加访问百度网盘的 User-Agent:

// ...
request = new Request(res.data.url, {
    ...request,
    headers: new Headers([
      ...Array.from(request.headers.entries()),
      ["User-Agent", "pan.baidu.com"]
    ])
  });
// ...

由于 cloudflare 默认域名 DNS 被污染,我们可以绑定自己的域名,配置好 worker 后添加路由:

设置区域为自己域名 <font style="color:rgb(48, 49, 51);">tph.fan</font> ,路由为 <font style="color:rgb(48, 49, 51);">alist-proxy.tph.fan/*</font>

最后在 alist 中添加存储,设置开启 web 代理并设置代理URL为 <font style="color:rgb(48, 49, 51);">http://alist-proxy.tph.fan</font>

参考链接:为alist设置代理地址-科学自习室

使用 FTP 功能

  1. 修改容器内 /data/config.json 文件,设置 sftp 开启
"sftp": {
  "enable": true,          
  "listen": ":5221"      
},       
  1. 修改容器端口映射
  2. 修改安全组

本地网盘

挂在本地路径到 docker

给 docker 容器的用户读写权限访问文件夹

root@iZ8vb9kyptw7s8q3nys57mZ:~# docker exec -it 7fb1f51da37f id
uid=1001(openlist) gid=1001(openlist) groups=1001(openlist)
root@iZ8vb9kyptw7s8q3nys57mZ:~# chown -R 1001:1001 objectStorage/

上传大小限制

    client_max_body_size 10G;  # 设置最大上传文件大小为 10G