Limour

Limour

临床医学在读。

[Reproduction] Set up Alist on Fly.io

After completing the tutorial by @moeyy titled “Deploying Alist with Fly.io”, there are some small details to optimize the experience, which I will record here.

Obtain Administrator Account#

flyctl ssh console # If it fails, open the deployed application page, refresh, and try a few more times
./alist admin random

Change Static Resource Address#

Cloudflare Reverse Proxy jsDelivr#

  1. Create a new Worker
// Replace with the site you want to mirror
const upstream = 'cdn.jsdelivr.net'
 
// If that site has a dedicated mobile adaptation site, otherwise keep it the same as above
const upstream_mobile = 'cdn.jsdelivr.net'
 
const blocked_region = []
 
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
 
const replace_dict = {
    '$upstream': 'jscdn.limour.top',
    '//cdn.jsdelivr.net': '//jscdn.limour.top'
}
 
// No need to change the following content
addEventListener('fetch', event => {
    event.respondWith(fetchAndApply(event.request));
})
 
async function fetchAndApply(request) {
 
    const region = request.headers.get('cf-ipcountry').toUpperCase();
    const ip_address = request.headers.get('cf-connecting-ip');
    const user_agent = request.headers.get('user-agent');
 
    let response = null;
    let url = new URL(request.url);
    let url_host = url.host;
 
    if (url.protocol == 'http:') {
        url.protocol = 'https:'
        response = Response.redirect(url.href);
        return response;
    }
 
    if (await device_status(user_agent)) {
        upstream_domain = upstream
    } else {
        upstream_domain = upstream_mobile
    }
 
    url.host = upstream_domain;
 
    if (blocked_region.includes(region)) {
        response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
            status: 403
        });
    } else if(blocked_ip_address.includes(ip_address)){
        response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
            status: 403
        });
    } else{
        let method = request.method;
        let request_headers = request.headers;
        let new_request_headers = new Headers(request_headers);
 
        new_request_headers.set('Host', upstream_domain);
        new_request_headers.set('Referer', url.href);
 
        let original_response = await fetch(url.href, {
            method: method,
            headers: new_request_headers
        })
 
        let original_response_clone = original_response.clone();
        let original_text = null;
        let response_headers = original_response.headers;
        let new_response_headers = new Headers(response_headers);
        let status = original_response.status;
 
        new_response_headers.set('access-control-allow-origin', '*');
        new_response_headers.set('access-control-allow-credentials', true);
        new_response_headers.delete('content-security-policy');
        new_response_headers.delete('content-security-policy-report-only');
        new_response_headers.delete('clear-site-data');
 
        const content_type = new_response_headers.get('content-type');
        if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
            original_text = await replace_response_text(original_response_clone, upstream_domain, url_host);
        } else {
            original_text = original_response_clone.body
        }
 
        response = new Response(original_text, {
            status,
            headers: new_response_headers
        })
    }
    return response;
}
 
async function replace_response_text(response, upstream_domain, host_name) {
    let text = await response.text()
 
    var i, j;
    for (i in replace_dict) {
        j = replace_dict[i]
        if (i == '$upstream') {
            i = upstream_domain
        } else if (i == '$custom_domain') {
            i = host_name
        }
 
        if (j == '$upstream') {
            j = upstream_domain
        } else if (j == '$custom_domain') {
            j = host_name
        }
 
        let re = new RegExp(i, 'g')
        text = text.replace(re, j);
    }
    return text;
}
 
async function device_status (user_agent_info) {
    var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
    var flag = true;
    for (var v = 0; v < agents.length; v++) {
        if (user_agent_info.indexOf(agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
}
  1. Trigger - Route set to jscdn.limour.top/*
    chrome_8iW7vWzDYC

Set Conversion Rules to Allow Cross-Domain#

chrome_1p9A79FzAR
chrome_JrSt0hs7Oj

Replace CDN#

In the AList management page, change all cdn.jsdelivr.net to your reverse proxy address.

Add Comment System#

  1. Deploy Waline on Vercel
  2. In AList management - Settings - Global - Custom Header, introduce Waline styles
<link rel="stylesheet" href="https://unpkg.com/@waline/client@v2/dist/waline.css" />

chrome_CvU6XxlFK6
3. In AList management - Metadata, introduce Waline client

#  <center> - Comments -
<div id="waline"></div>
<script type="module">
    import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs';
    init({
      el: '#waline',
      serverURL: 'https://comments.limour.top',
    });
</script>

chrome_dkHxZBrHC1

Waline Email Asynchronous Push#

Waline Email Asynchronous Push by Star Diary

mkdir -p ~/app/mailpush && cd ~/app/mailpush && nano docker-compose.yml
git clone --depth=1 https://github.com/soxft/waline-async-mail.git
cd waline-async-mail
nano config.example.yaml # Modify to your own email service
nano templates/guest.html && nano templates/owner.html # Modify to your own email templates
docker build -t xsot/waline-async-mail . && docker image prune
cd ~/app/mailpush
sudo docker-compose up -d
version: "3"
services:
  waline-async-mail:
    image: xsot/waline-async-mail:latest
    volumes:
      - ./waline-async-mail/config.example.yaml:/app/config.yaml
    restart: always
 
networks:
  default:
    external: true
    name: ngpm

Note that there is a "/" after "waline-async-mail/"

  • Add WEBHOOK in the environment variables, with the value https://api.limour.top/mail/limour
  • In Deployments, redeploy
  • WEBHOOK Explanation

Replace Waline with MongoDB#

  1. Create a free M0 database on the MongoDB official website, select Singapore as the region, and allow 0.0.0.0/0
  2. In the Waline project on Vercel, change the Region to Singapore in Settings/Functions
  3. Record the connection information in MongoDB, with the following options
  4. Choose Drivers as the connection method, Driver as Node.js, Version as 2.2.12 or later
  5. Go to the Waline management backend and export data
  6. Delete LEAN-related environment variables in Vercel, and add MongoDB connection information according to instructions
  7. In Vercel/Deployments, select the appropriate branch, click the three dots beside it, and choose Redeploy
  8. Go to the Waline management backend, re-register, and import data

Custom Domain#

  • DNS resolution can only be
  • Domain ownership verification is CNAME
    chrome_9TRCid0Vy7

Demo Address#

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.