Github
1
2
| #安装所需程序
sudo apt install nginx php7.4-fpm php7.4-mysql php7.4-fpm php7.4-mysql php7.4-cli php7.4-opcache certbot python3-certbot-nginx python3-certbot-dns-cloudflare
|
创建Index.php文件#
这里只需要修改路径
主路径#
1
2
| cd /var/www/html
nano index.php
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
| <?php
$pcPath = '/landscape';#这里的路径自行修改
$mobilePath = '/portrait';#这里的路径自行修改
// 函数:从目录中获取图片列表
function getImagesFromDir($path) {
$images = array();
if ($img_dir = @opendir($path)) {
while (false !== ($img_file = readdir($img_dir))) {
// 匹配 webp、jpg、jpeg、png、gif 格式的图片
if (preg_match("/\.(webp|jpg|jpeg|png|gif)$/i", $img_file)) {
$images[] = $img_file;
}
}
closedir($img_dir);
}
return $images;
}
// 函数:生成完整的图片路径
function generateImagePath($path, $img) {
return $path . '/' . $img;
}
// 检测用户代理以区分手机和电脑访问
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$isMobile = preg_match('/(android|iphone|ipad|ipod|blackberry|windows phone)/i', $userAgent);
// 根据访问设备设置图片路径
if ($isMobile) {
$path = $mobilePath;
} else {
$path = $pcPath;
}
// 缓存图片列表
$imgList = getImagesFromDir($path);
// 从列表中随机选择一张图片
shuffle($imgList);
$img = reset($imgList);
// 获取图片的格式
$img_extension = pathinfo($img, PATHINFO_EXTENSION);
// 根据图片的格式设置 Content-Type
switch ($img_extension) {
case 'webp':
header('Content-Type: image/webp');
break;
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'png':
header('Content-Type: image/png');
break;
case 'gif':
header('Content-Type: image/gif');
break;
// 添加其他格式的处理方式
// case 'bmp':
// header('Content-Type: image/bmp');
// break;
}
// 生成完整的图片路径
$img_path = generateImagePath($path, $img);
// 直接输出所选的随机图片
readfile($img_path);
?>
|
PC路径#
1
2
| mkdir /var/www/html/pc && cd /var/www/html/pc
nano index.php
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| <?php
$pcPath = '../landscape';#这里的路径自行修改
// 函数:从目录中获取图片列表
function getImagesFromDir($path) {
$images = array();
if ($img_dir = @opendir($path)) {
while (false !== ($img_file = readdir($img_dir))) {
// 匹配 webp、jpg、jpeg、png、gif 格式的图片
if (preg_match("/\.(webp|jpg|jpeg|png|gif)$/i", $img_file)) {
$images[] = $img_file;
}
}
closedir($img_dir);
}
return $images;
}
// 函数:生成完整的图片路径
function generateImagePath($path, $img) {
return $path . '/' . $img;
}
// 设置图片路径为 landscape
$path = $pcPath;
// 缓存图片列表
$imgList = getImagesFromDir($path);
// 从列表中随机选择一张图片
shuffle($imgList);
$img = reset($imgList);
// 获取图片的格式
$img_extension = pathinfo($img, PATHINFO_EXTENSION);
// 根据图片的格式设置 Content-Type
switch ($img_extension) {
case 'webp':
header('Content-Type: image/webp');
break;
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'png':
header('Content-Type: image/png');
break;
case 'gif':
header('Content-Type: image/gif');
break;
// 添加其他格式的处理方式
// case 'bmp':
// header('Content-Type: image/bmp');
// break;
}
// 生成完整的图片路径
$img_path = generateImagePath($path, $img);
// 直接输出所选的随机图片
readfile($img_path);
?>
|
Mobile路径#
1
2
| mkdir /var/www/html/mobile && cd /var/www/html/mobile
nano index.php
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| <?php
$pcPath = '../portrait';#这里的路径自行修改
// 函数:从目录中获取图片列表
function getImagesFromDir($path) {
$images = array();
if ($img_dir = @opendir($path)) {
while (false !== ($img_file = readdir($img_dir))) {
// 匹配 webp、jpg、jpeg、png、gif 格式的图片
if (preg_match("/\.(webp|jpg|jpeg|png|gif)$/i", $img_file)) {
$images[] = $img_file;
}
}
closedir($img_dir);
}
return $images;
}
// 函数:生成完整的图片路径
function generateImagePath($path, $img) {
return $path . '/' . $img;
}
// 设置图片路径为 portrait
$path = $pcPath;
// 缓存图片列表
$imgList = getImagesFromDir($path);
// 从列表中随机选择一张图片
shuffle($imgList);
$img = reset($imgList);
// 获取图片的格式
$img_extension = pathinfo($img, PATHINFO_EXTENSION);
// 根据图片的格式设置 Content-Type
switch ($img_extension) {
case 'webp':
header('Content-Type: image/webp');
break;
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'png':
header('Content-Type: image/png');
break;
case 'gif':
header('Content-Type: image/gif');
break;
// 添加其他格式的处理方式
// case 'bmp':
// header('Content-Type: image/bmp');
// break;
}
// 生成完整的图片路径
$img_path = generateImagePath($path, $img);
// 直接输出所选的随机图片
readfile($img_path);
?>
|
反代开启HTTPS#
1
2
3
4
| #清空默认配置
> /etc/nginx/sites-available/default
#手动编辑默认配置
sudo nano /etc/nginx/sites-available/default
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| server {
listen [::]:8080;
listen 8080;
server_name example.com; # 替换为你的域名以便下面申请域名
root /var/www/html; # 设置网站根目录
# 默认首页是 index.php 或其他文件(根据你的需求)
index index.php index.html index.htm;
# 处理根目录请求,直接返回根目录下的文件(如果存在)
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 处理 PHP 文件
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 防止访问 .ht 文件(如果有)
location ~ /\.ht {
deny all;
}
}
|
1
2
3
4
| #测试Nginx配置
sudo nginx -t
#重新加载Nginx配置
sudo systemctl reload nginx
|
现在可以访问ip:8080查看效果
开始申请证书#
1
2
3
4
5
6
7
8
9
| #从Cloudflare获取区域DNS API,这里可选,往下看
sudo nano /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = 你的API
#赋予权限
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
#使用CF-DNS申请证书,你不想关小黄云用这个,全称y就行
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d example.com #替换为你的域名
#直接申请证书,上面的申请完后可以用这个命令自动配置HTTPS,选1
sudo certbot --nginx -d example.com #替换为你的域名
|
示例配置#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
| server {
listen 80;
server_name example.com;
# 强制重定向到 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl ipv6only=on;
server_name example.com;
# SSL 证书配置
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/html;
index index.php index.html index.htm;
# 处理根目录请求
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 处理 /mobile 路径
location /mobile {
try_files $uri $uri/ /mobile/index.php?$query_string; # 如果是动态路由,调整路径
}
# 处理 /pc 路径
location /pc {
try_files $uri $uri/ /pc/index.php?$query_string; # 如果是动态路由,调整路径
}
# 处理 PHP 文件
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 禁止执行上传目录中的 PHP 文件
location ~ ^/uploads/.*\.php$ {
deny all;
}
}
# 防止访问 .ht 文件
location ~ /\.ht {
deny all;
}
# 压缩和缓存优化
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_types text/plain text/css application/javascript application/json application/xml application/xml+rss text/javascript;
gzip_min_length 1000;
location ~* \.(jpg|jpeg|png|gif|css|js|woff|woff2|ttf|svg)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
}
|
1
2
3
4
| #测试Nginx配置
sudo nginx -t
#重新加载Nginx配置
sudo systemctl reload nginx
|
到此就可以使用你的域名访问,使用/pc或/mobile显示不同方向图片
查看是否自动续期#
查看 certbot.timer 的状态
1
| sudo systemctl list-timers | grep certbot
|
如果看到类似以下的输出,表示 certbot.timer 服务已启用并正在运行:
1
| Thu 2025-04-23 00:00:00 UTC 12h left certbot.timer
|
查看 certbot.timer 服务是否正在运行
1
| systemctl status certbot.timer
|
如果服务未启用,你可以启用并启动它
1
| sudo systemctl enable --now certbot.timer
|
这会启用并立即启动 certbot.timer,使其每 12 小时自动检查证书续期。
图片处理代码#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| from PIL import Image
import os
# 检查图片方向
def get_image_orientation(image_path):
with Image.open(image_path) as img:
width, height = img.size
return "landscape" if width > height else "portrait"
# 转换图片为 WebP 格式
def convert_to_webp(image_path, output_folder, max_pixels=178956970):
try:
with Image.open(image_path) as img:
# Check image size
width, height = img.size
if width * height > max_pixels:
print(f"Skipping {image_path} because it exceeds the size limit.")
return
# Save the image as WebP
output_path = os.path.join(output_folder, os.path.splitext(os.path.basename(image_path))[0] + ".webp")
img.save(output_path, "webp")
except Exception as e:
print(f"Failed to convert {image_path}: {e}")
# 遍历文件夹中的图片
def process_images(input_folder, output_folder_landscape, output_folder_portrait):
for filename in os.listdir(input_folder):
if filename.endswith(('.jpg', '.jpeg', '.png')):
image_path = os.path.join(input_folder, filename)
orientation = get_image_orientation(image_path)
try:
if orientation == "landscape":
convert_to_webp(image_path, output_folder_landscape)
else:
convert_to_webp(image_path, output_folder_portrait)
except Exception as e:
print(f"Error processing {image_path}: {e}. Skipping this image.")
# 指定输入和输出文件夹
input_folder = "/root/photos"
output_folder_landscape = "/root/landscape"
output_folder_portrait = "/root/portrait"
# 执行转换
process_images(input_folder, output_folder_landscape, output_folder_portrait)
|