在Linux中自定义N卡的风扇转速曲线我个人对硬件的温度比较重视，认为是越低越好，显卡这玩意超过70度我觉得就已经是高温了。由于我已经主力使用Linux系统很久了，一直都是在需要给显卡上强度的时候，直接拉满显卡风扇。但是后面发现不是每时每刻都需要跑满的，没有负载的时候风扇还在呼呼吹确实是有点浪费了，于是就想搓一个bash脚本，用于显卡风扇控制。脚本本体没错，又是面向LLM编程！#!/bin/bash # 初始化上一次的风扇转速 last_speed=-1 while true; do # 获取 GPU 温度（单位：摄氏度） temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits -i 0) # 判断温度范围并计算风扇转速 if (( $(echo "$temp <= 40" | bc -l) )); then current_speed=40 elif (( $(echo "$temp >= 70" | bc -l) )); then current_speed=100 else # 线性插值：温度在 40~70°C 之间，速度从 40%~100% current_speed=$(echo "scale=0; 40 + 2 * ($temp - 40)" | bc) fi # 如果转速发生变化，才执行设置并输出调试信息 if [ "$current_speed" -ne "$last_speed" ]; then echo "GPU Temp: $temp°C → Fan Speed: $current_speed%" nvidia-settings -a "[gpu:0]/GPUFanControlState=1" -a "[fan:0]/GPUTargetFanSpeed=$current_speed" > /dev/null 2>&1 last_speed=$current_speed fi # 每秒检测一次 sleep 1 done脚本说明脚本逻辑：40度以下，转速40%，40度到70度，线性递增，到70度及以上时为100%。至于为什么不是停转？因为我的是涡轮卡，没法停（ ，需要的话请自行修改。使用方法：把代码保存为set_GPU_fan.sh，赋予执行权限后用root执行。建议配合tmux挂在后台。注意事项：这个脚本只针对单GPU，单风扇的情况，如果你是多GPU或者nvidia-settings厘米出现了多个风扇控制，就需要进行脚本的完善和修改。我这个脚本只在有桌面环境的情况下测试过没问题，对于无GUI的情况，我是没有测试过的，据说是要运行X Server才可以运行nvidia-settings。希望这个脚本可以更好的帮助你控制显卡温度。
二次开发 Typecho 后台服务器状态查看插件
发现Typecho后台服务器状态插件在翻Typecho插件的时候，我偶然发现了两双筷子写的Typecho后台服务器状态查看插件，于是就尝试了一下下。这个插件在桌面端网页没问题，感觉还挺不错的。但是一旦变成移动端，后台的布局就会出现问题，逼死强迫症。而且，CPU利用率有时候还会变成0.9999999999%这种离谱的数据，我寻思着就不能取两位小数好看一点吗？于是，我决定，自己修改代码，把服务器信息移动到页面底部的位置，并且修改显示数据的逻辑，让信息看着更加舒适一点。（其实也不完全是我写，是面向LLM编程 X）修改代码的过程首先，需要把注册方法的地方改为页面底部Typecho_Plugin::factory('admin/footer.php')->begin = array('LinuxInfo_Plugin', 'render');然后就是修改一下插入的样式：echo <<<STR $info_str STR;因为我觉的系统信息用鼠标悬浮预览不明显，于是修改为直接独立一行把信息全部展示：return <<<SYS_INFO 服务器信息: 持续运行：{$uptime}，Web服务器：{$_SERVER['SERVER_SOFTWARE']}，PHP 版本：{$php['version']}，SAPI 接口：{$php['sapi']}，PHP内存限制：{$php['mem_max']}，上传文件限制：{$php['up_max']} SYS_INFO;以及让LLM帮忙完善了CPU信息获取的逻辑：private static function cpu_info(){ function GetCoreInformation() { $data = file('/proc/stat'); $cores = []; foreach( $data as $line ) { if( preg_match('/^cpu[0-9]/', $line) ) { $info = explode(' ', $line); $cores[] = [ 'user' => $info[1], 'nice' => $info[2], 'sys' => $info[3], 'idle' => $info[4], 'iowait' => $info[5], 'irq' => $info[6], 'softirq' => $info[7] ]; } } return $cores; } function GetCpuPercentages($stat1, $stat2) { if(count($stat1) !== count($stat2)){ return; } $cpus = []; for( $i = 0, $l = count($stat1); $i < $l; $i++) { $dif = []; $dif['user'] = $stat2[$i]['user'] - $stat1[$i]['user']; $dif['nice'] = $stat2[$i]['nice'] - $stat1[$i]['nice']; $dif['sys'] = $stat2[$i]['sys'] - $stat1[$i]['sys']; $dif['idle'] = $stat2[$i]['idle'] - $stat1[$i]['idle']; $dif['iowait'] = $stat2[$i]['iowait'] - $stat1[$i]['iowait']; $dif['irq'] = $stat2[$i]['irq'] - $stat1[$i]['irq']; $dif['softirq'] = $stat2[$i]['softirq'] - $stat1[$i]['softirq']; $total = array_sum($dif); $cpu = []; foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 2); $cpus['CPU' . $i] = $cpu; } return $cpus; } $stat1 = GetCoreInformation(); sleep(1); $stat2 = GetCoreInformation(); $data = GetCpuPercentages($stat1, $stat2); $overall_cpu_usage = 0; $core_details = []; foreach ($data as $core => $usage) { $core_usage = 100 - $usage['idle']; $overall_cpu_usage += $core_usage; $core_details[] = "{$core}: " . number_format($core_usage, 2) . "%"; } $overall_cpu_usage = round($overall_cpu_usage / count($data), 2); $core_details_str = implode(", ", $core_details); $sys_load = sys_getloadavg(); $sys_load_1min = number_format($sys_load[0], 3); $sys_load_5min = number_format($sys_load[1], 3); $sys_load_15min = number_format($sys_load[2], 3); return <<<CPU_INFO CPU: {$overall_cpu_usage} % CPU_INFO; }原来的逻辑只是判断单个CPU的占有率，当CPU数量为多个的时候就会不准确，这里我优化成了整体利用率，并且悬停时会显示每个CPU的占用率信息。改造效果虽然不是彻底重构，但是我对改造后的插件还是比较满意的。手机的网页端也舒服了。修改后的插件分享修改后的插件已经放到了GitHub：Typecho-LinuxInfo反正源码也不多，我这里也可以直接放出来：Plugin.php:<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; /** * 查看系统信息，仅限 Linux 系统，基于两双筷子的插件进行二次开发，使用帮助 * * @package LinuxInfo * @author GTX690战术核显卡导弹 * @version 1.1.0 * @link https://www.nekopara.uk */ class LinuxInfo_Plugin implements Typecho_Plugin_Interface { // 插件名称 protected static $plugin_name = 'LinuxInfo'; /** * 激活插件方法,如果激活失败,直接抛出异常 * * @access public * @return void * @throws Typecho_Plugin_Exception */ public static function activate() { // 如果当前系统不是 linux 则抛出错误 if(PHP_OS != 'Linux') { throw new Typecho_Plugin_Exception(_t("此插件仅支持 Linux 系统")); } // 在后端页面底部 注册方法 Typecho_Plugin::factory('admin/footer.php')->begin = array('LinuxInfo_Plugin', 'render'); } /** * 禁用插件方法,如果禁用失败,直接抛出异常 * * @static * @access public * @return void * @throws Typecho_Plugin_Exception */ public static function deactivate(){} /** * 获取插件配置面板 * * @access public * @param Typecho_Widget_Helper_Form $form 配置面板 * @return void */ public static function config(Typecho_Widget_Helper_Form $form) { /** 分类名称 */ $show_item = array( 'cpu_info' => _t('CPU使用情况') . '（ CPU 使用率、系统负载）', 'mem_info' => _t('内存使用情况') . '（内存使用率、SWAP交换分区）', 'disk_info' => _t('磁盘使用情况') . '（磁盘使用率、磁盘已用空间、磁盘总空间）', 'sys_info' => _t('服务器信息') . ' （系统运行时间、服务器软件、PHP 版本、SAPI 接口、PHP 内存限制、上传文件限制）', ); // 设置默认选中 $show_option_value = ['cpu_info','mem_info','disk_info']; $ShowInfo = new Typecho_Widget_Helper_Form_Element_Checkbox('show_items',$show_item, $show_option_value, _t('选择显示系统信息')); $form->addInput($ShowInfo->multiMode()); $separator = new Typecho_Widget_Helper_Form_Element_Text('separator', NULL, ' ★ ', _t('分隔符'), '设置数据项分割字符'); $form->addInput($separator); } /** * 个人用户的配置面板 * * @access public * @param Typecho_Widget_Helper_Form $form * @return void */ public static function personalConfig(Typecho_Widget_Helper_Form $form){} /** * 插件实现方法 * * @access public * @return void */ public static function render() { $show_items = Typecho_Widget::widget('Widget_Options')->plugin(self::$plugin_name)->show_items; $separator = Typecho_Widget::widget('Widget_Options')->plugin(self::$plugin_name)->separator; // 获取 linux 系统消息 $info_str = ''; $show_items_max = count($show_items) - 1; foreach ($show_items as $show_item_k => $show_item) { $method = $show_item; if (method_exists(__CLASS__, $method)) { $info_str .= self::$method(); } if ($show_items_max != $show_item_k) { $info_str .= $separator; } } echo <<<STR $info_str STR; } // 获取CPU信息 private static function cpu_info(){ function GetCoreInformation() { $data = file('/proc/stat'); $cores = []; foreach( $data as $line ) { if( preg_match('/^cpu[0-9]/', $line) ) { $info = explode(' ', $line); $cores[] = [ 'user' => $info[1], 'nice' => $info[2], 'sys' => $info[3], 'idle' => $info[4], 'iowait' => $info[5], 'irq' => $info[6], 'softirq' => $info[7] ]; } } return $cores; } function GetCpuPercentages($stat1, $stat2) { if(count($stat1) !== count($stat2)){ return; } $cpus = []; for( $i = 0, $l = count($stat1); $i < $l; $i++) { $dif = []; $dif['user'] = $stat2[$i]['user'] - $stat1[$i]['user']; $dif['nice'] = $stat2[$i]['nice'] - $stat1[$i]['nice']; $dif['sys'] = $stat2[$i]['sys'] - $stat1[$i]['sys']; $dif['idle'] = $stat2[$i]['idle'] - $stat1[$i]['idle']; $dif['iowait'] = $stat2[$i]['iowait'] - $stat1[$i]['iowait']; $dif['irq'] = $stat2[$i]['irq'] - $stat1[$i]['irq']; $dif['softirq'] = $stat2[$i]['softirq'] - $stat1[$i]['softirq']; $total = array_sum($dif); $cpu = []; foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 2); $cpus['CPU' . $i] = $cpu; } return $cpus; } $stat1 = GetCoreInformation(); sleep(1); $stat2 = GetCoreInformation(); $data = GetCpuPercentages($stat1, $stat2); $overall_cpu_usage = 0; $core_details = []; foreach ($data as $core => $usage) { $core_usage = 100 - $usage['idle']; $overall_cpu_usage += $core_usage; $core_details[] = "{$core}: " . number_format($core_usage, 2) . "%"; } $overall_cpu_usage = round($overall_cpu_usage / count($data), 2); $core_details_str = implode(", ", $core_details); $sys_load = sys_getloadavg(); $sys_load_1min = number_format($sys_load[0], 3); $sys_load_5min = number_format($sys_load[1], 3); $sys_load_15min = number_format($sys_load[2], 3); return <<<CPU_INFO CPU: {$overall_cpu_usage} % CPU_INFO; } // 获取内存信息 private static function mem_info(){ if (false === ($str = @file("/proc/meminfo"))) return false; $str = implode("", $str); preg_match_all("/MemTotal\s{0,}\:+\s{0,}([\d\.]+).+?MemFree\s{0,}\:+\s{0,}([\d\.]+).+?Cached\s{0,}\:+\s{0,}([\d\.]+).+?SwapTotal\s{0,}\:+\s{0,}([\d\.]+).+?SwapFree\s{0,}\:+\s{0,}([\d\.]+)/s", $str, $buf); preg_match_all("/Buffers\s{0,}\:+\s{0,}([\d\.]+)/s", $str, $buffers); $mem_info['memTotal'] = round($buf[1][0]/1024, 2); $mem_info['memFree'] = round($buf[2][0]/1024, 2); $mem_info['memBuffers'] = round($buffers[1][0]/1024, 2); $mem_info['memCached'] = round($buf[3][0]/1024, 2); $mem_info['memUsed'] = $mem_info['memTotal']-$mem_info['memFree']; $mem_info['memPercent'] = (floatval($mem_info['memTotal'])!=0)?round($mem_info['memUsed']/$mem_info['memTotal']*100,2):0; $mem_info['memRealUsed'] = $mem_info['memTotal'] - $mem_info['memFree'] - $mem_info['memCached'] - $mem_info['memBuffers']; //真实内存使用 $mem_info['memRealFree'] = $mem_info['memTotal'] - $mem_info['memRealUsed']; //真实空闲 $mem_info['memRealPercent'] = (floatval($mem_info['memTotal'])!=0)?round($mem_info['memRealUsed']/$mem_info['memTotal']*100,2):0; //真实内存使用率 $mem_info['memCachedPercent'] = (floatval($mem_info['memCached'])!=0)?round($mem_info['memCached']/$mem_info['memTotal']*100,2):0; //Cached内存使用率 $mem_info['swapTotal'] = round($buf[4][0]/1024, 2); $mem_info['swapFree'] = round($buf[5][0]/1024, 2); $mem_info['swapUsed'] = round($mem_info['swapTotal']-$mem_info['swapFree'], 2); $mem_info['swapPercent'] = (floatval($mem_info['swapTotal'])!=0)?round($mem_info['swapUsed']/$mem_info['swapTotal']*100,2):0; $mem_per = round($mem_info['memRealUsed'] / $mem_info['memTotal'] * 100, 2); return <<<MEM_INFO 内存: {$mem_per} % MEM_INFO; } // 获取磁盘信息 private static function disk_info(){ $dt = round(@disk_total_space(".")/(1024*1024*1024), 2); //总 $df = round(@disk_free_space(".")/(1024*1024*1024), 2); //可用 $du = $dt-$df; //已用 $disk_use = round($du / $dt * 100, 2); return <<<DISK_INFO 硬盘: {$disk_use} % DISK_INFO; } // 获取 系统信息 private static function sys_info() { if (false === ($str = @file("/proc/uptime"))) return false; $str = explode(" ", implode("", $str)); $str = trim($str[0]); $min = $str / 60; $hours = $min / 60; $days = floor($hours / 24); $hours = floor($hours - ($days * 24)); $min = floor($min - ($days * 60 * 24) - ($hours * 60)); if ($days !== 0) $uptime = $days."天"; if ($hours !== 0) $uptime .= $hours."小时"; $uptime .= $min."分钟"; $php['version'] = PHP_VERSION; $php['sapi'] = php_sapi_name(); $php['mem_max'] = get_cfg_var('memory_limit'); $php['up_max'] = get_cfg_var('upload_max_filesize'); return <<<SYS_INFO 服务器信息: 持续运行：{$uptime}，Web服务器：{$_SERVER['SERVER_SOFTWARE']}，PHP 版本：{$php['version']}，SAPI 接口：{$php['sapi']}，PHP内存限制：{$php['mem_max']}，上传文件限制：{$php['up_max']} SYS_INFO; } }优先使用Github上面的吧，万一那天我修复一些问题，可能只会修改Github上面的仓库的内容而忘记修改这篇文章。当然，我希望以后不会出现问题。使用方法将GitHub上面的Plugin.php或者这个页面的Plugin.php内容保存下载，放到Typecho的插件目录usr/plugins/下的LinuxInfo文件夹（需要自己创建），例如：typecho/usr/plugins/LinuxInfo/Plugin.php，进入Typecho后台启用插件即可。默认不显示系统详细信息，需要自己勾选显示才会展示。不过，需要注意的是，这个插件仅可用于Linux系统，Windows系统不适用。谁用Windows做服务器啊？！！不会吧不会吧？最后还是要感谢一下两双筷子写出来这个有意思的插件。
浪潮SA5212M4风扇调速Python脚本写脚本的原因之前每次开机都要进BMC把风扇转速调低，不然吵得要死。但是又不能调得太低，因为如果调的太低怕一不留神温度就飙上去了，导致硬件出问题。正好前几天看到了一个别人用Python写的简易风扇一键调节脚本，但是只能设置固定转速，没办法根据温度动态调节。于是我重构了这个脚本，做到了根据温度动态调节风扇转速。环境要求系统要求：Linux（Windows不可用，因为没有sensors软件包）软件环境：Python3环境，sensors软件包（用于获取CPU温度）Python源代码import subprocess import re import http.client import time # 全局变量用于存储会话连接和令牌 conn = None session_cookie = None def login(IP, User, Password): global conn, session_cookie if conn is not None: conn.close() # 关闭旧连接 conn = http.client.HTTPConnection(IP) payload = "WEBVAR_USERNAME=" + User + "&WEBVAR_PASSWORD=" + Password headers = { 'Content-Type': "application/x-www-form-urlencoded", 'Origin': "http://{}".format(IP), 'Referer': "http://{}/index.html".format(IP), 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0", } conn.request("POST", "/rpc/WEBSES/create.asp", payload, headers) response = conn.getresponse().read().decode("utf-8") match = re.search(r"'SESSION_COOKIE' : '([^']*)'", response) if match: session_cookie = match.group(1) else: raise ValueError("SESSION_COOKIE not found in the string") def set_fan_speed(IP, fan_speeds): global conn, session_cookie # 设置风扇为手动模式 payload1 = "MODE=1" headers1 = { 'Content-Type': "application/x-www-form-urlencoded", 'Cookie': "BMC_IP_ADDR={}; SessionCookie=".format(IP) + session_cookie, } conn.request("POST", "/rpc/setfanmode.asp", payload1, headers1) conn.getresponse() # 调整风扇转速 headers2 = { 'Content-Type': "application/x-www-form-urlencoded", 'Cookie': "SessionCookie=" + session_cookie + "; BMC_IP_ADDR={}".format(IP), } for fan_ID, Speed_x in fan_speeds.items(): payload2 = "ID=" + fan_ID + "&PERCENT=" + Speed_x conn.request("POST", "/rpc/setfanspeed.asp", payload2, headers2) conn.getresponse() print("调整风扇{}转速{}%".format(fan_ID, Speed_x)) def get_package_temperatures(): output = subprocess.check_output(['sensors']).decode('utf-8') pattern = re.compile( r'^Package id (\d+):\s+\+([\d.]+)\.?\s*°C', re.MULTILINE ) matches = pattern.findall(output) result = {f"Package id {package_id}": int(float(temp_str)) for package_id, temp_str in matches} return result def compute_fan_speed(temp): if temp <= 45: return 10 elif temp >= 70: return 100 else: return int(10 + (temp - 45) * (90 / (70 - 45))) last_temp = None if __name__ == "__main__": IP = "192.168.0.6" #服务器BMC内网IP地址 User = "admin" #服务器BMC管理员账号 Password = "admin" #服务器BMC管理员密码 # 首次登录 login(IP, User, Password) while True: try: temperatures = get_package_temperatures() max_temp = max(temperatures.values()) if last_temp is None or abs(max_temp - last_temp) >= 2: fan_speed = str(compute_fan_speed(max_temp)) set_fan_speed(IP, {"0": fan_speed, "2": str(compute_fan_speed(max_temp)+3), "4": fan_speed, "6": fan_speed}) last_temp = max_temp print(temperatures, max_temp) else: continue #print(f"温度变化不足2度 ({last_temp}℃ -> {max_temp}℃)，跳过风扇转速调整.") except Exception as e: print(f"遇到错误: {e}") # 发生错误时重新登录 login(IP, User, Password) time.sleep(2)代码说明风扇转速的策略是，45度以下风扇转速10%，超过45度开始线性增加，70度时风扇转速100%。可以根据需要修改compute_fan_speed函数的逻辑。02号风扇默认比其他风扇转速高3%，因为这个风扇对应的是CPU1，为了安装显卡换了散热器，并且阻挡较多温度较高，所以风扇转速设置偏高一点平衡两边温度。如果不需要安装显卡可以修改set_fan_speed(IP, {"0": fan_speed, "2": str(compute_fan_speed(max_temp)+3), "4": fan_speed, "6": fan_speed})这部分，风扇速度传入的是一个字典，键值对是风扇ID:转速百分比。如果你的服务器是其他有八个风扇的型号（例如SA5112M4），那只需要吧传入的字典部分改成八个对应的键值对即可。希望这个风扇调节脚本可以帮到你。
为Alpine Linux 3.20 编译安装ZeroTier没有ZeroTier软件包！由于我云服务器使用的是Alpine Linux来最大程度节省资源用于实际服务，而ZeroTier官方没有给出Alpine Linux的安装包，所以要用点野路子才能安装上。使用官方的安装脚本 Be Like:Neko_SG:~# curl -s https://install.zerotier.com | bash *** ZeroTier Service Quick Install for Unix-like Systems *** Tested OSes / distributions: *** MacOS (10.13+) (just installs ZeroTier One.pkg) *** Debian Linux (7+) *** RedHat/CentOS Linux (6+) *** Fedora Linux (16+) *** SuSE Linux (12+) *** Mint Linux (20+) *** Kali Linux (2024.1+) *** Supported architectures vary by OS / distribution. We try to support *** every system architecture supported by the target. *** Please report problems by opening a GitHub issue or Pull Request at: *** https://github.com/zerotier/install.zerotier.com *** Please include the content of `/etc/os-release` for your distribution. *** Detecting Linux Distribution *** Unknown or unsupported distribution! Aborting. 想从包管理器安装 Be Like:Neko_SG:~# apk add zerotier fetch https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/latest-stable/community/x86_64/APKINDEX.tar.gz ERROR: unable to select packages: zerotier (no such package): required by: world[zerotier] Neko_SG:~# apk add zerotier-one ERROR: unable to select packages: zerotier-one (no such package): required by: world[zerotier-one] Neko_SG:~# apk search zerotier Neko_SG:~# 一个思路是去用别的发行版的软件包，解包提取二进制文件。但是由于Alpine Linux是用的C语言库是musl而不是libc，大部分发行版用点都是libc，所以不一定可以兼容。还有一个办法，那就相当硬核了，自己编译后，安装。这个方法肯定会遇到很多技术上的问题，所以也是最有挑战性的一条路子，但是，我还是决定开干。下载源代码之所以可以这么玩，是因为ZeroTier是开源的。 开源大法好！先创建一个用于干活的文件夹，然后直接从Github的Release下载源代码：mkdir /data/zerotier cd /data/zerotier wget https://github.com/zerotier/ZeroTierOne/archive/refs/tags/1.14.2.zip unzip 1.14.2.zip cd ZeroTierOne-1.14.2/准备相关环境进行编译因为Alpine Linux是轻量发行版，所以缺失的库很多，需要自己手动装。我也是边报错边安装，搞了好久。我的版本是Alpine Linux 3.20，以下是需要安装的软件包：apk add util-linux pkgconfig openssl-dev libffi cargo linux-headers g++ gcc make进行编译进入源代码目录，执行：make -j$(nproc)如果没有报错，一个会顺利在目录生成一个zerotier-one文件，然后还会有zerotier-cli和zerotier-idtool这两个软链接链接到zerotier-one。如果是这样，那就编译成功了。运行前的准备如果你直接运行。那大概率并不会出现ZeroTier的虚拟网络接口，因为相关的内核模块并没有启用。当然，这个虚拟的接口需要先加入了网络才会开启，不然也是没有的。运行这个命令开启内核模块：modprobe tun如果报错不行的话，试一下重启系统，模块要重启才能生效。但是，这样子设置的话，肯定重启就没了。所以要持久化设置，就需要修改/etc/modules文件：nano /etc/modules在文件后面加上tun：af_packet ipv6 tun这样设置后，重启也可以正常生效了。ZeroTier，启动！直接在编译好的目录下，执行./zerotier-one -d即可运行。但是，ZeroTier也还是会在/usr/lib/zerotier-one/目录下生成相关的配置文件，我个人更倾向于把那三个生成的文件放到这个目录下，跟官方的一致。不出意外的话，就能在ifconfig里面看到虚拟的接口了。编译好的文件分享如果你用的也是Alpine Linux，那你可以用我编译好的ZeroTier。这是编译好的文件下载地址：zerotier-musl.zip同样的，需要安装对应的软件包才能使用：apk add util-linux cargo linux-headers装完之后，参照上面的运行前准备部分，照做就行了。
个性化你的Filebrowser！Filebroswer的优点为什么选择Filebroswer呢？原因不外乎就是以下几点∶支持https实时同步文件目录更改，更新及时不需要数据库界面美观友好管理方便支持多用户支持分享文件可以定制界面而最后这一点，也为后面进行美化奠定了基础。前置准备为了保证操作的环境相同，如果你是按照这篇教程来，记得选择File Browser 2.28.0。FileBrowser的基本配置，可以参考我之前的文章：个性化Filebrowser界面，NAS也要Kawaii~~~!个性化Filebrowser你可以快速把我预设的文件下载后直接解压到Filebrowser所在文件夹，修改替换背景图，完成个性化。文件目录结构长这样：├── filebrowser ├── filebrowser.db └── style ├── custom.css ├── favicon.ico ├── img │ ├── background.jpg │ ├── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── mstile-70x70.png │ │ └── safari-pinned-tab.svg │ ├── login.jpg │ ├── logo.svg │ └── lolicon.ttf └── manifest.json 4 directories, 21 files其中，最重要的配置文件就是custom.css了。这个文件决定了全局的外观。style文件夹我已经打包好了：style.7z下载回去，解压到程序的目录按照下图设置即可看到效果：下面是设置完成后的效果，我设置的是粉色主题的，稍微搭配一点蓝色：登陆页面：主界面：多选文件：复制文件对话框：移动文件对话框：删除文件对话框：切换不同的显示方式：下载文件对话框：上传文件对话框：文件信息对话框：搜索界面：设置界面：上传文件界面：CSS文件内容和解释custom.css文件内容这个文件定义了几乎全部的样式，文件内容如下： /** 页面字体 */ @font-face { font-family: 'cute'; src: local('cute'), local('cute'), url(/static/img/lolicon.ttf) format('truetype'); } * { font-family: "cute", sans-serif; } /** 加载动画 */ .spinner > div { background-color: #ff5f77; backdrop-filter: blur(6px); background-color: orangered\0; /* IE 样式 */ } /** 普通文字、字体图标颜色 */ .action, #listing h2, #search .boxes h3, .card h3, .collapsible > label *, .dashboard p label, .message { color: #ff5f77; } /** 链接文字颜色 */ a { color: #ff5f77; backdrop-filter: blur(6px); } /** 输入框、表格标题文字颜色 */ #search.active i, #search.active input, table th { backdrop-filter: blur(6px); color: #ff5f77; } /** 主体、弹窗颜色 */ #loading, #login, #search.active #input, body, header, .ace-chrome .ace_gutter-active-line { background-image: url(/static/img/background.jpg); background-repeat: no-repeat; background-attachment: fixed; background-position: center center; background-attachment: fixed; background-size: cover; color: #ff5f77 ; } /** 文件夹颜色 */ .file-icons [data-dir="true"] i { color: #ff5f77; } /** 搜索界面图标颜色 */ #search .boxes > div > div { background: #ff5f77; color: rgb(255, 255, 255); text-align: center; width: 10em; padding: 1em; cursor: pointer; margin-bottom: 1em; margin-right: 1em; -moz-box-flex: 1; flex-grow: 1; } /** 多选状态栏颜色 */ #listing #multiple-selection { position: fixed; bottom: -4em; left: 0px; z-index: 99999; width: 100%; background-color: #ff5f77a1; height: 4em; padding: 0.5em 0.5em 0.5em 1em; -moz-box-pack: justify; justify-content: space-between; transition: bottom 0.2s; } /** 多选项目颜色 */ #listing .item[aria-selected="true"] { background: #66ccffc4 !important; color: var(--item-selected) !important; } /* 设置容量显示条颜色 */ .vue-simple-progress { background: #66ccff !important; } /* 设置容量显示条颜色 */ .vue-simple-progress-bar { background: #ff6781 !important; } /* 设置选项卡颜色 */ .dashboard #nav ul li.active { border-color: #CD1076; color: #CD1076; } /** 定义卡片 */ .card{ border-radius: 2em; border: 1px solid #ff6781; background-color:transparent; backdrop-filter: blur(6px); color: #CD1076 ; } /** 定义卡片按钮 */ .button { outline: 0px; padding: 0.5em 1em; border-radius: 0.1em; cursor: pointer; background:#ff5f77; color: rgb(255, 255, 255); border: 1px solid rgba(0, 0, 0, 0.05); box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 5px; transition: 0.1s; } /** 定义卡片按钮 */ .button--flat { color: #e93654; background: transparent; -webkit-box-shadow: 0 0 0; box-shadow: 0 0; border: 0; text-transform: uppercase; } /** 定义容量显示下面的小字颜色 */ .credits { font-size: 0.6em; margin: 3em 2.5em; color: #e56c81; } /** 取消变暗覆盖 */ .overlay { background-color: rgba(0, 0, 0, 0); position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; z-index: 9999; visibility: hidden; opacity: 0; animation: 0.1s forwards show; } /** 定义搜索区 */ #search .boxes{ background-color:transparent; backdrop-filter: blur(6px); color: #CD1076 ; } /** 定义搜索框 */ #search input { border-radius: 2em; padding: .5em 1em; background: #fff5f6b8; border: 2px solid #ffd5dc; -webkit-transition: .2s ease all; transition: .2s ease all; color: #ff5474; margin: 3; } /** 搜索页面、列表标题样式 */ #search #input, #search #result, .input, #listing.list .item.header, .ace-chrome .ace_gutter, .share__box__download, .file-list li:hover { background-color:transparent; backdrop-filter: blur(6px); color: #CD1076 ; } /** 列表项目、文本编辑、命令行、文件分享样式 */ #listing .item, .ace-chrome, .shell, .share__box { background-color:transparent; backdrop-filter: blur(6px); color: #CD1076; } /** 加载页面、登录页面信息提示 */ #loading::after, #login::after { position: absolute; bottom: 6px; width: 100%; display: block; font-size: 22px; text-align: center; content: ''; color: #FF1493; /* IE 样式 */ bottom: 30px\0; font-size: 36px\0; color: tomato\0; } /** 登录页面背景图 */ #login { background-image: url(/static/img/login.jpg); } /** 登录页面LOGO大小 */ #login img { width: 8em; height: 8em; } /** 登录页面按钮定义 */ #login .button { outline: 0; border: 0; padding: .5em 1em; border-radius: 2em; cursor: pointer; background: #ff6781; color: #fff; border: 2px solid #ffd5dc; -webkit-box-shadow: 0 0 5px rgba(0,0,0,.05); box-shadow: 0 0 5px rgba(0,0,0,.05); -webkit-transition: .1s ease all; transition: .1s ease all; } /** 定义输入框 */ .input { border-radius: 2em; padding: .5em 1em; background: #fff5f6b8; border: 2px solid #ffd5dc; -webkit-transition: .2s ease all; transition: .2s ease all; color: #ff5474; margin: 3; } /** 定义登陆界面提示框 */ #login .wrong { border-radius: 2em; background: #ff5474; color: #fff; padding: .5em; text-align: center; -webkit-animation: .2s opac forwards; animation: .2s opac forwards; }文件每个功能区块有注释解释，可以根据需要修改，下面是详细说明。每个部分的详细说明页面字体定义了一个名为 'cute' 的自定义字体，并应用于整个页面。/** 页面字体 */ @font-face { font-family: 'cute'; src: local('cute'), url(/static/img/lolicon.ttf) format('truetype'); } * { font-family: "cute", sans-serif; }加载动画为加载动画中的元素设置了背景颜色和模糊效果。特别地，为了兼容IE浏览器，添加了额外的样式。/** 加载动画 */ .spinner > div { background-color: #ff5f77; backdrop-filter: blur(6px); background-color: orangered\0; /* IE 样式 */ }文字颜色为普通文字、链接文字、输入框及表格标题文字设置了统一的颜色。/** 普通文字、字体图标颜色 */ .action, #listing h2, #search .boxes h3, .card h3, .collapsible > label *, .dashboard p label, .message { color: #ff5f77; } /** 链接文字颜色 */ a { color: #ff5f77; backdrop-filter: blur(6px); } /** 输入框、表格标题文字颜色 */ #search.active i, #search.active input, table th { backdrop-filter: blur(6px); color: #ff5f77; }主体、弹窗颜色为页面主体、弹出窗口等设置了背景图片和文本颜色。/** 主体、弹窗颜色 */ #loading, #login, #search.active #input, body, header, .ace-chrome .ace_gutter-active-line { background-image: url(/static/img/background.jpg); background-repeat: no-repeat; background-attachment: fixed; background-position: center center; background-size: cover; color: #ff5f77; }文件夹颜色、搜索界面图标颜色、多选状态栏颜色、多选项目颜色这些规则为特定元素设置了颜色。/** 文件夹颜色 */ .file-icons [data-dir="true"] i { color: #ff5f77; } /** 搜索界面图标颜色 */ #search .boxes > div > div { background: #ff5f77; color: rgb(255, 255, 255); text-align: center; width: 10em; padding: 1em; cursor: pointer; margin-bottom: 1em; margin-right: 1em; flex-grow: 1; } /** 多选状态栏颜色 */ #listing #multiple-selection { position: fixed; bottom: -4em; left: 0px; z-index: 99999; width: 100%; background-color: rgba(255, 85, 119, 0.63); height: 4em; padding: 0.5em; justify-content: space-between; transition: bottom 0.2s; } /** 多选项目颜色 */ #listing .item[aria-selected="true"] { background: rgba(102, 204, 255, 0.77); color: var(--item-selected) !important; }容量显示条颜色、选项卡颜色、卡片定义、按钮定义、登录界面样式这些规则为UI组件如进度条、选项卡、卡片、按钮以及登录界面定义了样式。/* 设置容量显示条颜色 */ .vue-simple-progress { background: #66ccff !important; } .vue-simple-progress-bar { background: #ff6781 !important; } /* 设置选项卡颜色 */ .dashboard #nav ul li.active { border-color: #CD1076; color: #CD1076; } /** 定义卡片 */ .card{ border-radius: 2em; border: 1px solid #ff6781; background-color:transparent; backdrop-filter: blur(6px); color: #CD1076 ; } /** 定义卡片按钮 */ .button { outline: 0px; padding: 0.5em 1em; border-radius: 0.1em; cursor: pointer; background:#ff5f77; color: rgb(255, 255, 255); border: 1px solid rgba(0, 0, 0, 0.05); box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 5px; transition: 0.1s; } .button--flat { color: #e93654; background: transparent; box-shadow: 0 0; border: 0; text-transform: uppercase; } .credits { font-size: 0.6em; margin: 3em 2.5em; color: #e56c81; } /** 取消变暗覆盖 */ .overlay { background-color: rgba(0, 0, 0, 0); position: fixed; top: 0px; left: 0px; height: 100%; width: 100%; z-index: 9999; visibility: hidden; opacity: 0; animation: 0.1s forwards show; } /** 登录页面样式 */ #login { background-image: url(/static/img/login.jpg); img { width: 8em; height: 8em; } .button { outline: 0; border: 0; padding: .5em 1em; border-radius: 2em; cursor: pointer; background: #ff6781; color: #fff; border: 2px solid #ffd5dc; box-shadow: 0 0 5px rgba(0,0,0,.05); transition: .1s ease all; } .wrong { border-radius: 2em; background: #ff5474; color: #fff; padding: .5em; text-align: center; animation: .2s opac forwards; } }
二次开发ACME网页版申请客户端跑路了！今天突然发现，之前用的host.mw申请一年免费证书的网站，一年免费证书跑路了，只有90天免费证书了。于是，我在想之前用的那个ACME单网页客户端会不会也有可能跑路。因为他之前的Gitee的page前段时间已经没办法访问了。有一说一，确实挺好用的，贴个GitHub地址：github.com/xiangyuecn/ACME-HTML-Web-Browser-Client自主创新我就去GitHub把他的HTML文件下载了下来，进行"自研"，删掉了一点我看着不太舒服的东西，然后加上点装饰效果，进行"自主创新"。以下是"自主创新"后的代码: 免费SSL证书申请 Loading... 网页版ACME客户端 ACME Web Browser Client 功能用途本网页客户端用于：向 Let's Encrypt、ZeroSSL、Google 等支持 ACME 协议的证书颁发机构，免费申请获得用于 HTTPS 的 SSL/TLS 域名证书（RSA、ECC/ECDSA），支持多域名和通配符泛域名；只需在现代浏览器上操作即可获得 PEM 格式纯文本的域名证书，不依赖操作系统环境，无需下载和安装软件，纯手动操作，只专注于申请获得证书这一件事。 Functional useThis web client is used to: apply for free SSL/TLS domain name certificates (RSA, ECC/ECDSA) for HTTPS from Let's Encrypt , ZeroSSL , Google and other certificate authorities that support the ACME protocol, and support multiple domain names and wildcard pan-domain names; Simply operate on a modern browser to obtain a domain name certificate in plain text in PEM format, does not depend on the operating system environment, does not need to download and install software, and is purely manual, only focus on the only thing that is to apply for and obtain a certificate. 简单易用点点鼠标 Ctrl+C Ctrl+V 就能完成证书的申请，全程需要的操作少，每一步都有保姆级操作提示，UI友好大气美观；本客户端不需要注册账号、更不需要登录。 Easy to useClick the mouse and Ctrl+C Ctrl+V to complete the certificate application. The whole process requires less operations, and there are nanny level operation prompts at each step; UI friendly, atmospheric and beautiful; This client does not need to register an account, and does not need to log in. 开源项目本网页客户端源码已开源，访问网址由托管仓库提供，源码透明可追溯。 Open source projectThe source code of the client side of this webpage has been open sourced, and the access URL is provided by the hosting warehouse, and the source code is transparent and traceable. 单一文件本网页客户端仅一个静态 HTML 文件，不依赖其他任何文件；因此可以直接保存到你本地（右键-另存为），即可通过浏览器打开。 A single fileThis web client is only a single static HTML web page file and does not depend on any other files; therefore, it can be directly saved to your local (right-click - save as), and you can open it through a browser. 数据安全除了你指定证书颁发机构的 ACME 接口地址外，本网页客户端不会向其他任何地址发送数据，通过浏览器控制台很容易做到网络数据审查。 Data securityExcept for the ACME interface address of the certificate authority you specify, this web client will not send data to any other address, and it is easy to check the network data through the browser console. 系统安全纯网页应用，不会也无法对你的电脑系统做出任何修改。 System securityPure web application, will not and cannot make any modification to your computer system. 证书过期风险提醒由于本网页客户端只能纯手动操作，不支持自动续期，需注意在证书过期前重新生申请新证书（免费证书普遍90天有效期，届时只需重复操作一遍即可），或使用 acme.sh 等客户端自动化续期。 Certificate Expiration Risk AlertSince this web client can only be operated manually and does not support automatic renewal, you should pay attention to apply for a new certificate before the certificate expires (free certificates are generally valid for 90 days, you only need to repeat the operation at that time), or use acme.sh and other client automatic renewal. 步骤一：选择证书颁发机构 Step 1: Select a Certificate Authority * 证书颁发机构 ACME(v2, RFC 8555) 服务URL： Certificate Authority ACME (v2, RFC 8555) Service URL: Let's Encrypt ZeroSSL Google 手动填写URL Fill in the URL manually 测试用[不要选] For testing, don't choose Let's Encrypt: 请按照下面的操作步骤提示进行申请即可得到证书，证书有效期90天。 Please follow the operation steps prompts below to apply, and you can get the certificate, which is valid for 90 days. ZeroSSL: 此URL可能需要先根据下面的提示进行操作来消除跨域不能访问的问题。 This URL may need to be operated according to the prompts below to eliminate the problem of cross-domain inaccessibility. 申请证书前，你需要根据ZeroSSL的官方文档，先注册ZeroSSL账号并生成一个EAB凭据，每次申请证书时使用此EAB凭据，按照下面的操作步骤提示进行申请即可得到证书，证书有效期90天。 Before applying for a certificate, you need to follow ZeroSSL's official documents, register a ZeroSSL account and generate an EAB credential, and use this EAB credential every time you apply for a certificate, follow the operation steps prompts below to apply, and you can get the certificate, which is valid for 90 days. Google Trust Services: 此URL可能需要先根据下面的提示进行操作来消除跨域不能访问的问题。 This URL may need to be operated according to the prompts below to eliminate the problem of cross-domain inaccessibility. 申请证书前，你需要根据Google的官方文档，在Google Cloud中生成一个EAB凭据，每次申请证书时使用此EAB凭据，按照下面的操作步骤提示进行申请即可得到证书，证书有效期90天。 Before applying for a certificate, you need to follow Google's official documents, generate an EAB credential in Google Cloud, and use this EAB credential every time you apply for a certificate, follow the operation steps prompts below to apply, and you can get the certificate, which is valid for 90 days. 注意：因为同一个Google EAB凭据只能绑定到一个ACME账户（私钥），因此你在首次申请证书时，必须同时保存好在第二步操作中新创建的或手动填写的ACME账户私钥，下次申请证书时使用此EAB凭据必须和已保存的ACME账户私钥一起使用。 Note: Because the same Google EAB credential can only be bound to one ACME account (Private key), when you apply for a certificate for the first time, you must also save the newly generated or manually filled ACME account private key in the second step, this EAB credential must be used together with the saved ACME account private key when applying for a certificate next time. 读取服务目录 Read service directory 步骤二：证书配置 Step 2: Certificate Configuration 等待中，请先完成第一步... Waiting, please complete step 1 first... 温馨提示：如果上次申请过证书，可以拖拽已下载保存的记录LOG文件到本页面，将自动填充上次的配置信息。 Reminder: If you have applied for a certificate last time, you can drag and drop the downloaded and saved record LOG file to this page, and the last configuration information will be automatically filled in. * 证书中要包含的域名： Domain name to be included in the certificate: 一个证书可以包含多个域名（支持通配符），比如填写：a.com, *.a.com, b.com, *.b.com；第一个域名将作为证书的通用名称（Common Name）；带通配符的域名只支持DNS验证，其他域名支持上传文件验证；注意：填了www.a.com时，一般需要额外填上a.com。 A certificate can contain multiple domain names (wildcard are supported), for example, fill in: a.com, *.a.com, b.com, *.b.com; the first domain name will be used as the Common Name of the certificate; Domain names with wildcard only support DNS verification, and other domain names support upload file verification ; Note: When www.a.com is filled in, it is generally necessary to fill in a.com additionally. 记住 Remember * 证书的私钥： Private key of certificate: 生成或填写的私钥仅用于ACME接口签名，支持RSA(2048位+)、ECC(曲线)私钥；注意：证书私钥的类型决定了申请到的证书是RSA证书还是ECC(ECDSA)证书，RSA类型适用性更广也更常见；本客户端不会对此私钥进行保存或发送给其他任何人；证书签发后在部署到服务器时，需使用到此私钥；建议每次申请证书时均生成新的证书私钥。 The generated or filled private key is only used for ACME interface signature, and supports RSA (2048-bit+) and ECC ( curve) private keys; Note: The type of certificate private key determines whether the applied certificate is an RSA certificate or a ECC(ECDSA) certificate, RSA type is more widely applicable and more common; this client will not save or send this private key to anyone else; this private key needs to be used when deploying to the server after the certificate is issued; it is recommended to generate a new certificate private key every time you apply for a certificate. 创建新RSA私钥 Generate RSA private key 创建新ECC私钥 Generate ECC private key 手动填写私钥 Manually fill in the private key * ACME账户的私钥： Private key of ACME account: 生成或填写的私钥仅用于ACME接口签名，支持RSA(2048位+)、ECC(曲线)私钥；账户私钥类型对证书无影响；本客户端不会对此私钥进行保存或发送给其他任何人；一个私钥相当于一个账户，可用于吊销已签发的证书；建议每次申请证书时使用相同的一个私钥（这样短期内多次申请证书时，验证域名所有权的参数极有可能会保持相同），不过每次都生成一个新的私钥大部分情况下也不会有问题。 The generated or filled private key is only used for ACME interface signature, and supports RSA (2048-bit+) and ECC ( curve) private keys; the account private key type has no effect on the certificate; this client will not save or send this private key to anyone else; A private key is equivalent to an account and can be used to revoke an issued certificate; it is recommended to use the same private key every time you apply for a certificate (in this way, the parameters used to verify the domain name ownership are likely to remain identical when multiple certificate applications are made in a short period of time); However, generating a new private key every time will not be a problem in most cases. 注意：如果你选择的ACME服务（比如Google）要求提供EAB凭据并且限制了同一个EAB凭据只能绑定到一个ACME账户（私钥），那每次使用此EAB凭据时必须使用相同的一个私钥（首次时如果新创建了私钥，此新私钥需立即保存起来下次和此EAB凭据一起使用）。 Note: If the ACME service you choose (such as Google) requires EAB credentials and limits the same EAB credentials to only one ACME account (private key), then you must use the same private key every time you use this EAB credential (if you generate a new private key for the first time, this new private key needs to be saved immediately and used with this EAB credential next time). 创建新RSA私钥 Generate RSA private key 创建新ECC私钥 Generate ECC private key 手动填写私钥 Manually fill in the private key * ACME账户的联系邮箱： Contact email of ACME account: 此邮箱地址用于证书颁发机构给你发送邮件，比如：证书过期前的续期通知提醒。 This email address is used by the certificate authority to send you emails, such as a reminder of renewal notice before the certificate expires. 记住 Remember EAB凭据： EAB Credentials: 当前ACME服务要求提供外部账号绑定凭据（External Account Binding），比如ZeroSSL：你可以在ZeroSSL的管理控制台的 Developer 中获得此凭据，所以你需要先注册一个ZeroSSL的账号。 The current ACME service requires external account binding credentials, such as ZeroSSL: You can obtain this credentials in the Developer of the ZeroSSL management console, so you need to register a ZeroSSL account first. *EAB KID: *HMAC KEY: 确定 OK 步骤三：验证域名所有权 Step 3: Verify Domain Ownership 等待中，请先完成第二步... Waiting, please complete step 2 first... 请给每个域名选择一个你合适的验证方式（推荐采用DNS验证，比较简单和通用），然后根据显示的提示完成对应的配置操作。 Please select a suitable verification method for each domain name (DNS Verify is recommended, which is relatively simple and common), and then complete the corresponding configuration operations according to the displayed prompts. 请每个域名选择好对应的验证方式，根据显示的提示进行对应的配置操作；必须所有域名配置完成后，再来点击下面的“开始验证”按钮进行验证，如果验证失败，需要返回第二步重新开始操作。 Please select the corresponding verify method for each domain name, and perform the corresponding configuration operation according to the displayed prompts; after all domain names are configured, click the "Start Verify" button below to verify, if the verify fails, you need to go back to the step 2 Start the operation. 开始验证 Start Verify 取消 Cancel 重试 Retry 步骤四：下载保存证书PEM文件 Step 4: Download and save the certificate PEM file 等待中，请先完成第三步... Waiting, please complete step 3 first... * 保存证书PEM文件： Save certificate PEM file: 必须保存此文件，请点击下载按钮下载，或者将证书文本内容复制保存为文件（PEM纯文本格式）；文件名后缀可改成 .crt 或 .cer，这样在Windows中能直接双击打开查看。本PEM格式文件已包含你的域名证书、和完整证书链，文本中第一个CERTIFICATE为你的域名证书，后面的为证书颁发机构的中间证书和根证书，如过有需要你可以自行拆分成多个.pem文件。 This file must be saved, please click the download button to download, or copy the text content of the certificate and save it as file (PEM plain text format); the file name suffix can be changed to .crt or .cer , so that it can be directly double-clicked to open and view in Windows. This PEM format file already contains your domain name certificate and complete certificate chain. The first CERTIFICATE in the text is your domain name certificate, followed by the intermediate certificate and root certificate of the certificate authority, if necessary, you can split it into multiple .pem files. 下载保存 Download * 保存证书私钥KEY文件： Save the certificate private key KEY file: 请点击下载按钮下载，或者将私钥文本内容复制保存为文件（PEM纯文本格式，.key后缀可自行修改成.pem）。如果第二步操作中你手动填写了证书私钥，此处的证书私钥和你填写的是完全一样的，可以不需要重复保存；如果你是新创建的证书私钥，则你必须下载保存此证书私钥文件。 Please click the download button to download, or copy and save the text content of the private key as file (PEM plain text format, the .key suffix can be modified to .pem by yourself). If you manually filled in the certificate private key in the step 2, the certificate private key here is exactly the same as what you filled in, and you don’t need to save it repeatedly; if you are a newly created certificate private key, you must download and save it This certificate private key file. 下载保存 Download * 保存记录LOG文件： Save the record LOG file: 建议下载保存此文件，本记录文件包含了所有数据，包括：证书PEM文本、证书私钥PEM文本、账户私钥PEM文本、所有配置参数。下次你需要续签新证书时，可以将本记录文件直接拖拽进本页面，会自动填写所有参数。 It is recommended to download and save this file. This record file contains all data, including: certificate PEM text, certificate private key PEM text, account private key PEM text, and all configuration parameters. Next time you need to renew a new certificate, you can drag and drop the record file directly into this page, and all parameters will be filled in automatically. 下载保存 Download 你需要其他格式的证书文件？ Do you need certificate files in other formats? 大部分服务器程序支持直接使用 + 来配置开启HTTPS（比如Nginx），如果你需要 *.pfx、*.p12 格式的证书（比如用于IIS），请用下面命令将PEM证书转换成 pfx/p12 格式： Most server programs support directly using + to configure and enable HTTPS (such as Nginx). If you need a certificate in *.pfx or *.p12 format (such as for IIS), please use the following command to convert the PEM certificate Convert to pfx/p12 format: openssl pkcs12 -export -out .pfx -inkey -in IIS证书链缺失？ IIS certificate chain missing? 对于Windows IIS服务器，你需要将证书链安装到“本地计算机”的“中间证书颁发机构”中；请将PEM证书中的所有证书拆分成单个PEM文件（后缀改成.crt或.cer），然后将系统中缺失的中间证书双击打开然后安装进去；详细参考： For Windows IIS server, you need to install the certificate chain into "Intermediate Certification Authorities" in "Local Computer"; please split all certificates in PEM certificate into a single PEM file (change the suffix to .crt or .cer), then double-click to open the missing intermediate certificate in the system Then install it; detailed reference: http://support.microsoft.com/kb/954755 本客户端部分原理简介 Introduction to the principle of this client 得益于现代浏览器的 crypto.subtle 对加密功能标准化，不依赖其他任何js库就能在网页上实现 RSA、ECC 的加密、解密、签名、验证、和密钥对生成。在本客户端内的 X509 对象中：用 X509.CreateCSR 来生成CSR，用 X509.KeyGenerate 来创建PEM格式密钥，用 X509.KeyParse 来解析PEM格式密钥，用 X509.KeyExport 来导出PEM格式密钥；这些功能都是根据相应的标准用js代码在二进制层面上实现的，二进制数据操作封装在了 ASN1 对象中：实现了 ASN.1 标准的二进制解析和封包，使用 ASN1.ParsePEM 方法可以解析任意的PEM格式密钥或证书。以上这些都是实现ACME网页客户端的核心基础。 Thanks to the standardization of encryption functions by crypto.subtle of modern browsers, RSA and ECC encryption, decryption, signature, verification, and key pair generation can be implemented on web pages without relying on any other js library. In the X509 object in this client: use X509.CreateCSR to generate CSR, use X509.KeyGenerate to create PEM format key, use X509.KeyParse to parse PEM format key, use X509.KeyExport to export PEM format key; These functions are implemented at the binary level with js code according to the corresponding standards, and binary data operations are encapsulated in ASN1 objects: ASN.1 standard binary parsing and encapsulation are implemented, Arbitrary PEM format keys or certificates can be parsed using the ASN1.ParsePEM method. These are the core foundations for implementing the ACME web client. 然后就是对接ACME实现证书的签发，和实现交互UI；对接ACME可以直接参考 RFC 8555 标准。有些证书颁发机构的ACME服务对浏览器支持不良，未提供齐全的 Access-Control-* 响应头，导致网页内无法直接调用服务接口；目前采用的解决办法非常简单粗暴，比如ZeroSSL：检测到此ACME服务存在跨域问题时，会调用 acmeReadDirGotoCORS() 方法告诉用户操作步骤（你可以点此手动调用此方法），通过在他们的页面内运行本客户端来消除跨域问题（既然打不过，那就加入他们）。 Then it is to connect with ACME to realize certificate issuance and realize interactive UI; for connecting with ACME, you can directly refer to the RFC 8555 standard. The ACME services of some certificate authorities do not support browsers well, and do not provide complete Access-Control-* response headers, so that the service interface cannot be called directly in the web page; the current solution is very simple and rude, such as ZeroSSL: detect this ACME When there is a cross-domain problem with the service, the acmeReadDirGotoCORS() method will be called to tell the user the operation steps (you can call this method manually by clicking here), and the cross-domain problem will be eliminated by running this client in their page (if we can't beat them, we'd better join them). Language: 中文 | EN 部署页面最终页面我部署到了Cloudflare page，主要是为了方便自己使用吧，不然每次都记不住那个GitHubpage的地址。如果你要用的话也可以来用，网址是ssl.nekopara.uk
让你的 Filebrowser 变好看为什么要个性化？虽然filebriwser本身就是单文件的一个轻量级网盘服务端，简洁美观，但是对于我这种喜欢骚里骚气的人来说，纯白色的背景和图标显然不够好看，于是，我就需要把它个性化。准备工作相关的个性化文件需要放在程序同一个目录的style文件夹内，然后进行设置即可生效，虽然官方文档也写了如何个性化，但是写的不够清楚。于是我在网上东拼西凑，找到了设置的方法，进行整合，需要的可以直接使用我整合过的版本。我的版本设置了登陆界面背景，主页面背景，程序图标，界面字体，界面颜色。绝大部分的设置都在custom.css文件内，可以修改。对于图像，字体，图标等直接替换文件就可以了，不需要改设置文件，就是图标必须是svg格式的。下面是custom.css的内容： /** 页面字体 */ @font-face { font-family: 'cute'; src: local('cute'), local('cute'), url(/static/img/cute.ttf) format('truetype'); } * { font-family: "cute", sans-serif; } /** 加载动画 */ .spinner > div { background-color: #ff5f77; backdrop-filter: blur(6px); background-color: orangered\0; /* IE 样式 */ } /** 普通文字、字体图标颜色 */ .action, #listing h2, #search .boxes h3, .card h3, .collapsible > label *, .dashboard p label, .message { color: #ff5f77; } /** 链接文字颜色 */ a { color: #ff5f77; backdrop-filter: blur(6px); } /** 输入框、表格标题文字颜色 */ #search.active i, #search.active input, table th { backdrop-filter: blur(6px); color: #ff5f77; } /** 主体、弹窗颜色 */ #loading, #login, #search.active #input, body, header, .card, #search .boxes, .ace-chrome .ace_gutter-active-line { background-image: url(/static/img/background.jpg); background-repeat: no-repeat; background-attachment: fixed; background-position: center center; background-attachment: fixed; background-size: cover; color: #ff5f77 ; } /** 搜索页面、列表标题样式 */ #search #input, #search #result, .input, #listing.list .item.header, .ace-chrome .ace_gutter, .share__box__download, .file-list li:hover { background-color:transparent; backdrop-filter: blur(6px); color: #CD1076 ; } /** 列表项目、文本编辑、命令行、文件分享样式 */ #listing .item, .ace-chrome, .shell, .share__box { background-color:transparent; backdrop-filter: blur(6px); color: #CD1076; } /** 加载页面、登录页面信息提示 */ #loading::after, #login::after { position: absolute; bottom: 6px; width: 100%; display: block; font-size: 26px; text-align: center; content: ''; color: #FF1493; /* IE 样式 */ bottom: 30px\0; font-size: 36px\0; color: tomato\0; } /** 加载页面、登录页面背景图 */ #login { background-image: url(/static/img/login.jpg); } #login img { width: 8em; height: 8em; }整合包下载：这个是我设置好的整合包，稍微设置一下就可以用了：linux_filebrowser_style.zip进行设置：下载fliebrowser,也可以直接下上面说的整合包。上面的整合包已经把主题设置好了，即开即用。进入文件所在目录，运行filebrowser:./filebrowser然后使用Ctrl+C终止程序，进行基本设置。让全部IP都可以访问：./filebrowser config set -a 0.0.0.0更改储存路径：（可选）./filebrowser config set -r /path/to/storage/folder/更改监听端口：（可选）./filebrowser config set -p 2333设置证书以使用https:（可选，前提是你有域名，并且申请了证书）./filebrowser config set -t /path/to/certs/example_com.pem ./filebrowser config set -k /path/to/certs/example_com.key我的整合包只进行了第一步的设置。设置好后，启动filebrowser：./filebrowser打开浏览器，地址输入127.0.0.1:8080即可访问。登陆用户名和密码都是admin,记得及时修改密码！登陆后，点击设置，把语言改成中文：然后设置品牌设置，更新后，刷新浏览器就可以看到效果了：
最骚高考倒计时软件软件介绍这个软件是我2021年高考完后心血来潮写的软件。就是一个比较恶搞的高考倒计时软件，具体的操作可以看我的B站视频。运行截图：下载地址：注意！因为这个软件的行为有点恶毒，可能会被杀毒软件报毒！如果你不放心的话可以虚拟机试一下嘛，我敢发誓这玩意绝对没问题！T-minus.rar