diff --git a/build/linux/euler-copilot-web.spec b/build/linux/euler-copilot-web.spec index 56979ee20eb1edb6f9dbd91f2e9be39e1c9d2d74..2a99210757ee94a542318a903c9fa0108d9260da 100644 --- a/build/linux/euler-copilot-web.spec +++ b/build/linux/euler-copilot-web.spec @@ -35,6 +35,8 @@ Packager: openEuler BuildRequires: curl BuildRequires: zstd +Requires: nginx + %description openEuler 智能化解决方案 Web 前端 @@ -104,16 +106,27 @@ cat %{_sourcedir}/offline_node_modules-%{_electron_arch}.tar.zst.part0 \ > offline_node_modules-%{_electron_arch}.tar.zst if [ -f offline_node_modules-%{_electron_arch}.tar.zst ]; then - zstd -d offline_node_modules-%{_electron_arch}.tar.zst -c | tar -xf - + zstd -d offline_node_modules-%{_electron_arch}.tar.zst -c | tar -xf - fi # Install pnpm packages # pnpm install --offline -# Build the app +# Build Electron app pnpm run package:linux +# Build Web app +pnpm run build + %install +# Web 主包安装 +mkdir -p %{buildroot}/usr/share/euler-copilot-web +mkdir -p %{buildroot}/etc/nginx/conf.d +cp -a %{_builddir}/%{name}-%{version}/dist/. %{buildroot}/usr/share/euler-copilot-web/ +chmod -R a+rX %{buildroot}/usr/share/euler-copilot-web +cp -a %{_builddir}/%{name}-%{version}/build/linux/nginx.conf.local.tmpl %{buildroot}/etc/nginx/conf.d/euler-copilot-web.conf + +# Electron 客户端安装 mkdir -p %{buildroot}/opt/Intelligence mkdir -p %{buildroot}/usr/share/applications # 创建图标目录 @@ -143,13 +156,18 @@ cp -a %{_builddir}/%{name}-%{version}/build/icons/512x512.png %{buildroot}/usr/s %files -# 主包(暂时留空) +# Web 主包安装内容 +%dir /usr/share/euler-copilot-web +%dir /usr/share/euler-copilot-web/assets +%attr(0644, root, root) /usr/share/euler-copilot-web/*.* +%attr(0644, root, root) /usr/share/euler-copilot-web/assets/* +%config(noreplace) /etc/nginx/conf.d/euler-copilot-web.conf %files -n euler-copilot-desktop # 应用安装目录及其所有内容 %dir /opt/Intelligence -%attr(0755, root, root) /opt/Intelligence/* +%attr(0755, root, root) /opt/Intelligence/** # 桌面与图标 %attr(0644, root, root) /usr/share/applications/euler-copilot-desktop.desktop %attr(0644, root, root) /usr/share/icons/hicolor/16x16/apps/euler-copilot-desktop.png @@ -163,6 +181,14 @@ cp -a %{_builddir}/%{name}-%{version}/build/icons/512x512.png %{buildroot}/usr/s %attr(0644, root, root) /usr/share/icons/hicolor/512x512/apps/euler-copilot-desktop.png +%post +#!/bin/bash +# Web 主包安装后,检测 nginx 服务,若已运行则重启,否则跳过 +if systemctl is-active --quiet nginx; then + systemctl restart nginx +fi + + %post -n euler-copilot-desktop -p /bin/sh #!/bin/bash @@ -203,23 +229,23 @@ fi # Unfortunately, at the moment AppArmor doesn't have a good story for backwards compatibility. # https://askubuntu.com/questions/1517272/writing-a-backwards-compatible-apparmor-profile if apparmor_status --enabled > /dev/null 2>&1; then - APPARMOR_PROFILE_SOURCE='/opt/Intelligence/resources/apparmor-profile' - APPARMOR_PROFILE_TARGET='/etc/apparmor.d/euler-copilot-desktop' - if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then - cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET" - - # Updating the current AppArmor profile is not possible and probably not meaningful in a chroot'ed environment. - # Use cases are for example environments where images for clients are maintained. - # There, AppArmor might correctly be installed, but live updating makes no sense. - if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then - # Extra flags taken from dh_apparmor: - # > By using '-W -T' we ensure that any abstraction updates are also pulled in. - # https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport - apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET" + APPARMOR_PROFILE_SOURCE='/opt/Intelligence/resources/apparmor-profile' + APPARMOR_PROFILE_TARGET='/etc/apparmor.d/euler-copilot-desktop' + if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then + cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET" + + # Updating the current AppArmor profile is not possible and probably not meaningful in a chroot'ed environment. + # Use cases are for example environments where images for clients are maintained. + # There, AppArmor might correctly be installed, but live updating makes no sense. + if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then + # Extra flags taken from dh_apparmor: + # > By using '-W -T' we ensure that any abstraction updates are also pulled in. + # https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport + apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET" + fi + else + echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile" fi - else - echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile" - fi fi @@ -237,7 +263,7 @@ APPARMOR_PROFILE_DEST='/etc/apparmor.d/euler-copilot-desktop' # Remove apparmor profile. if [ -f "$APPARMOR_PROFILE_DEST" ]; then - rm -f "$APPARMOR_PROFILE_DEST" + rm -f "$APPARMOR_PROFILE_DEST" fi diff --git a/build/linux/nginx.conf.local.tmpl b/build/linux/nginx.conf.local.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..a7a3d14043f2611dcec897ba28cc113aa8316316 --- /dev/null +++ b/build/linux/nginx.conf.local.tmpl @@ -0,0 +1,86 @@ +server { + listen 8080 default_server; + server_name _; + charset utf-8; + + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options nosniff; + add_header Referrer-Policy "no-referrer"; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; always"; + add_header Cache-Control "no-cache"; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: base64;"; + + resolver 8.8.8.8 8.8.4.4 valid=60s; + resolver_timeout 5s; + + if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$) { + return 444; + } + + location ~ /\. { + deny all; + return 404; + } + + location / { + root /usr/share/euler-copilot-web; + try_files $uri $uri/ /index.html; + if (!-e $request_filename) { + return 404; + } + } + + location /copilot { + alias /usr/share/euler-copilot-web; + index index.html; + try_files $uri $uri/ /index.html; + } + + location /login { + root /usr/share/euler-copilot-web; + try_files $uri $uri/ /index.html; + } + + location /api/health_check { + deny all; + return 404; + } + + location /api/ { + proxy_set_header X-Forwarded-For $http_x_real_ip; + add_header Cache-Control "no-cache,no-store,must-revalidate"; + add_header X-Accel-Buffering no; + proxy_buffering off; + proxy_intercept_errors on; + + error_page 404 /404.html; + proxy_read_timeout 500s; + proxy_connect_timeout 500s; + + proxy_pass http://127.0.0.1:8002/api/; + } + + error_page 401 402 403 405 406 407 413 414 /error.html; + error_page 404 /404.html; + error_page 500 501 502 503 504 505 /error.html; + + location = /404 { + return 404; + } + + location = /404.html { + root /usr/share/euler-copilot-web; + internal; + } + + location = /error.html { + root /usr/share/euler-copilot-web; + internal; + } + + location /assets/ { + alias /usr/share/euler-copilot-web/assets/; + expires 30d; + add_header Cache-Control public; + } +}