Picuang
部署本地图床,踩坑记录准备部署一个本地图床,用来存储博客文章的图片。之所以选择 Picuang
来构建,既方便又安全可控,而且都是陈辉大佬的项目,可以无缝配置进 Solo 博客系统。 Picuang
图床使用 Tomcat 部署,虽然方便,不过也有些小坑,特此记录一下。
1# 安装 Java 17
2sudo apt install openjdk-17-jdk
3
4# 安装目录
5mkdir -p /opt/tomcat9/
6cd /opt/tomcat9/
7
8# 添加 tomcat 用户
9useradd -r -d /opt/tomcat9 -s /bin/false tomcat
10
11# 下载 tomcat 9,最新版本可以去 apache 官网查看
12# https://tomcat.apache.org/download-90.cgi
13wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.84/bin/apache-tomcat-9.0.84.tar.gz
14
15# 解压,并去除默认的顶层目录
16tar -zxzf apache-tomcat-9.0.84.tar.gz -C /opt/tomcat9 --strip-components=1
17
18# 为 tomcat 用户添加目录的所有权限
19chown -R tomcat: /opt/tomcat9/{logs,temp,webapps,work}
20chown -R :tomcat /opt/tomcat9/
21chmod -R g+r /opt/tomcat9/conf
22chmod g+x /opt/tomcat9/conf
23chown -R tomcat /opt/tomcat9/logs/
24
25# 配置环境变量
26echo 'export CATALINA_HOME="/opt/tomcat9"' > /etc/profile.d/tomcat9.sh
27
28# 测试 JAVA_HOME 环境变量
29echo $JAVA_HOME
30# 如果不存在,则需要额外配置,可以使用此命令找到 Java 位置
31update-java-alternatives -l
32
33# 重启 tomcat9 环境变量
34source /etc/profile.d/tomcat9.sh
35
36# 配置 tomcat web 管理账户
37vim /opt/tomcat9/conf/tomcat-users.xml
38# 根据注释添加条目
39<user username="admin" password="<must-be-changed>" roles="manager-gui"/>
40
41# 打开防火墙端口 8080
42ufw allow 8080
43
44# 运行 tomcat 启动脚本
45bash /opt/tomcat9/bin/startup.sh
46
47# 关闭服务
48bash /opt/tomcat9/bin/shutdown.sh
49
50# 运行成功后,可以设置 systemd 服务
51vim /etc/systemd/system/tomcat9.service
输入 tomcat9.service
内容如下:
1[Unit]
2Description=Apache Tomcat 9 Web Application Server
3Documentation=https://tomcat.apache.org/tomcat-9.0-doc/index.html
4After=network.target
5
6[Service]
7Type=forking
8User=tomcat
9Group=tomcat
10
11Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
12Environment="CATALINA_HOME=/opt/tomcat9"
13Environment="CATALINA_BASE=/opt/tomcat9"
14Environment="JAVA_OPTS=-Djava.awt.headless=true"
15
16ExecStart=/opt/tomcat9/bin/startup.sh
17ExecStop=/opt/tomcat9/bin/shutdown.sh
18
19[Install]
20WantedBy=multi-user.target
最后启动 Tomcat 服务
1# 启动 tomcat 服务
2systemctl daemon-reload
3systemctl enable --now tomcat9
frp
反向代理(可选)注:如果你的 tomcat 服务直接部署在云端,则这一步可以忽略;
使用frp
反向代理,映射本地机器到公网访问,frp
的完整配置过程略;
1# 修改 frpc 配置文件
2vim /opt/frp_0.33.0_linux_amd64/frpc.ini
添加新的代理字段,自定义 VPS 端的 Tomcat 服务端口为 58080
1# 配置 Tomcat9 服务
2[tomcat]
3type = tcp
4local_ip = 127.0.0.1
5local_port = 8080
6remote_port = 8080
然后重新配置 service 服务
1sudo cp frpc.ini /etc/frp
2sudo systemctl restart frpc
在 VPS 端开启 8080 的 ufw 防火墙和安全组,在浏览器中输入your_ip:8080
,出现 Tomcat 欢迎页面即表示安装成功。
Picuang
图床 1# war 包安装路径 /opt/tomcat9/webapps/
2
3# 下载 war 包
4wget https://github.com/adlered/Picuang/releases/download/V2.4/picuang2.4_v2.war
5
6# 复制包
7mv picuang2.4_v2.war /opt/tomcat9/webapps/picuang.war
8
9# 重启 tomcat 服务
10sudo systemctl restart tomcat9
上传图片的默认位置:uploadImages
详细路径: /opt/tomcat9/webapps/picuang/WEB-INF/classes/static/uploadImages/
此时在浏览器上输入your_ip:8080
,则可以看到 Picuang
的服务已经启动好了。
第一次启动服务管理,需要设置管理员密码。
从这里开始就是比较坑的地方了,我在 Picuang
的解包目录下根本找不到这个 config.ini
,也不知道这个配置文件应该是什么样的。
此时这个图床服务基本上算是启动完成,图片也可以正常上传,但是由于管理员密码设置的缺失,使得无法进行后台配置,而且任意匿名用户都能上传图片,这样肯定是不行的。
使用 IDEA 导入源代码,找到 Prop.java
是配置这个 config.ini 的源代码,打个记录输出控制台。在 IDEA 的执行环境下,这个配置文件的位置是项目的根目录,也即E:\projects\picture\Picuang-2.4
。
在服务器端重新编译 Picuang
,需要安装 Maven
1# 安装 maven
2sudo apt install maven
3
4# 克隆 Picuang 源代码并解压
5git clone https://github.com/adlered/Picuang.git
6
7# 使用 maven 编译项目
8mvn clean package
编译好的 war 包在 target 目录下,把修改后的 war 包复制到 Tomcat 的 webapps 目录下重启服务;
作为对比,在 Tomcat 中执行项目的控制台信息,保存在 Tomcat 目录下的 logs/catalina.out
日志中;
可以看出,在 Tomcat 容器中,这里的 config.ini
文件因为权限不够,配置出现了问题;
我们修改一下 Tomcat 的服务配置,把启动服务用户临时改为 root;
1# 临时修改 systemd 服务
2vim /etc/systemd/system/tomcat9.service
修改tomcat9.service
内容,修改 User 字段
1[Service]
2Type=forking
3User=root
4Group=
重启 Tomcat 服务
1systemctl daemon-reload
2systemctl restart tomcat9
重启 Tomcat 服务之后,可以看到 读取 config.ini 成功了;
那么这个文件到底创建在哪儿了呢?没错,就在绝对路径的根目录/
下:
由于根目录/
不属于 tomcat 用户,自然在 tomcat 服务中无法对其进行修改操作;
此时最简单的解决办法,我们可以在这个 config.ini
文件内输入管理员密码,然后保持使用 root 用户运行 tomcat 服务即可;
当然,最好的解决办法还是稍微修改一下 config.ini
这个文件的位置,最好放在一个合适的位置,方便查询备份;
这里简单修改一下 Prop.java
中所有关于 config.ini
这个文件的路径,包括 del(), put(), get(), reload() 这四个方法;
1 public static void del() {
2 File file = new File("/opt/tomcat9/webapps/picuang/config.ini");
3 file.delete();
4 }
5
6 public static void put() {
7
8 System.out.println("当前 config.ini 的设置目录是:" + System.getProperty("user.dir"));
9 try {
10 properties.load(new BufferedInputStream(new FileInputStream("/opt/tomcat9/webapps/picuang/config.ini")));
11 System.out.println("读取 config.ini 成功");
12 } catch (FileNotFoundException e) {
13 Logger.log("Generating new profile...");
14 properties.put("imageUploadedCount", "0");
15 properties.put("version", version);
16 properties.put("password", "");
17 properties.put("adminOnly", "off");
18 properties.put("uploadLimit", "1:1");
19 properties.put("cloneLimit", "3:1");
20 try {
21 properties.store(new BufferedOutputStream(new FileOutputStream("/opt/tomcat9/webapps/picuang/config.ini")), "Save Configs File.");
22 System.out.println("新建 config.ini 成功");
23 } catch (FileNotFoundException FNFE) {
24 FNFE.printStackTrace();
25 } catch (IOException IOE) {
26 IOE.printStackTrace();
27 }
28 } catch (IOException IOE) {
29 IOE.printStackTrace();
30 }
31 }
32
33 public static String get(String key) {
34 return properties.getProperty(key);
35 }
36
37 public static void set(String key, String value) {
38 try {
39 properties.setProperty(key, value);
40 Logger.log("[Prop] Set key '" + key + "' to value '" + value + "'");
41 PrintWriter printWriter = new PrintWriter(new FileWriter("/opt/tomcat9/webapps/picuang/config.ini"), true);
42 Set set = properties.keySet();
43 for (Object object : set) {
44 String k = (String) object;
45 String v = properties.getProperty(k);
46 printWriter.println(k + "=" + v);
47 }
48 } catch (Exception e) {
49 e.printStackTrace();
50 }
51 if (!key.equals("imageUploadedCount")) {
52 reload();
53 }
54 }
55
56 public static String getVersion() {
57 return version;
58 }
59
60 public static void reload() {
61 Logger.log("Reloading profile...");
62 // Reload properties
63 try {
64 properties.load(new BufferedInputStream(new FileInputStream("/opt/tomcat9/webapps/picuang/config.ini")));
65 } catch (Exception e) {}
66 // Upload limit
67 try {
68 String uploadLimitMaster = get("uploadLimit");
69 if (uploadLimitMaster.contains(":")) {
70 int uploadLimitTime = Integer.parseInt(uploadLimitMaster.split(":")[0]);
71 int uploadLimitTimes = Integer.parseInt(uploadLimitMaster.split(":")[1]);
72 UploadController.uploadLimiter = new SimpleCurrentLimiter(uploadLimitTime, uploadLimitTimes);
73 Logger.log("Upload limit custom setting loaded (" + uploadLimitTimes + " times in " + uploadLimitTime + " second) .");
74 }
75 } catch (Exception e) {}
76 // Clone limit
77 try {
78 String cloneLimitMaster = get("cloneLimit");
79 if (cloneLimitMaster.contains(":")) {
80 int cloneLimitTime = Integer.parseInt(cloneLimitMaster.split(":")[0]);
81 int cloneLimitTimes = Integer.parseInt(cloneLimitMaster.split(":")[1]);
82 UploadController.cloneLimiter = new SimpleCurrentLimiter(cloneLimitTime, cloneLimitTimes);
83 Logger.log("Clone limit custom setting loaded (" + cloneLimitTimes + " times in " + cloneLimitTime + " second) .");
84 }
85 } catch (Exception e) {}
86 }
最后用 Maven 重新编译 war 包,部署到 Tomcat,此时就能在 /opt/tomcat9/webapps/picuang/
下找到自动生成的config.ini
文件了,内容如下:
1#Save Configs File.
2#Fri Jan 05 13:36:54 CST 2024
3version=V2.4
4adminOnly=on
5password=
6imageUploadedCount=0
7cloneLimit=3\:1
8uploadLimit=1\:1
在 password 字段输入密码,一切完美~
此时就可以设置非管理员账号就无法上传图片了