Limour

Limour

临床医学在读。

[Reproduction] Set up Alist on Fly.io

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

Obtain Admin 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 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

Conversion Rule Settings Allow Cross-Domain#

chrome_1p9A79FzAR
chrome_JrSt0hs7Oj

Replace CDN#

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

Add Comment System#

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

chrome_CvU6XxlFK6
3. Introduce Waline client in AList management - Metadata

#  <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 Instructions

Replace Waline with MongoDB#

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

Custom Domain Name#

  • 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.