Tự host HRConvert2: chuyển file riêng tư trên VPS
Chạy HRConvert2 trên VPS để file khách hàng không qua website miễn phí. Có hướng dẫn Docker hoặc Apache, bubblewrap sandbox, giới hạn upload và cleanup.
Vì sao nên tự host một công cụ chuyển đổi file
Công cụ chuyển đổi file tự host giữ file trên ổ đĩa của bạn. Đó là lý do duy nhất để chạy công cụ này. Một website chuyển đổi miễn phí nhận file upload nhưng không cho bạn biết sau đó file được xử lý thế nào. Nếu file là hợp đồng đã ký của khách hàng hoặc hồ sơ bệnh án được scan, thì ngay việc upload file đã là một sự cố bảo mật. HRConvert2 là một server chuyển đổi file dạng kéo thả, được viết bằng PHP và cấp phép theo GPLv3. Version 3.7.4 được phát hành vào ngày 18 August 2026 và dự án công bố hỗ trợ 488 định dạng.
HRConvert2 không có database, account hoặc cookie. Mỗi user chỉ tương ứng với một thư mục tạm thời. Mọi conversion đều do một công cụ dòng lệnh chạy local thực hiện: LibreOffice cho tài liệu, FFmpeg cho audio và video, ImageMagick cho hình ảnh, Tesseract cho nhận dạng ký tự quang học (OCR), cùng nhiều công cụ nhỏ hơn cho các định dạng còn lại. HRConvert2 cung cấp trang upload, pipeline và cơ chế cleanup cho toàn bộ quy trình.
Công cụ này chuyển file từ định dạng này sang định dạng khác. Đây không phải là bộ office chạy trên browser. Nếu bạn muốn mọi người chỉnh sửa tài liệu trong một tab, hãy xem OnlyOffice và Collabora tự host thay thế. Đây cũng không phải là storage. Output sau khi chuyển đổi được thiết kế để xóa, vì vậy nếu file cần được lưu trữ, hãy dùng file manager tự host.
Cần gì
Debian hoặc Ubuntu, Apache 2.4, PHP 8 trở lên và bubblewrap. Bubblewrap (bwrap) là sandbox và bắt buộc phải có: server không thể tạo sandbox sẽ từ chối chuyển đổi thay vì chạy mà không có sandbox. README upstream nói Raspberry Pi Model B+ là đủ, và điều đó đúng với phần PHP. Các binary converter mới quyết định giới hạn phần cứng thực tế; phần này được trình bày ở bên dưới.
Có 2 cách để bắt đầu. Docker image có thể chạy ngay tối nay. Cài Apache và PHP mất khoảng một buổi tối, nhưng cho bạn biết chính xác những gì đang có trên máy.
Chạy tối nay bằng Docker
Image chứa mọi binary của converter nên khá lớn: khoảng 3 GB tính đến August 2026. Kiểm tra dung lượng disk còn trống trước khi pull.
Tag rất quan trọng ở đây. Tag mới nhất được publish trên Docker Hub tính đến 17 August 2026 là v3.7.2, còn release GitHub mới nhất là v3.7.4. Tag latest có thể thay đổi ngoài dự kiến, và ứng dụng này có bề mặt parser lớn, nên hãy pin một version và chỉ upgrade khi chủ động thực hiện.
docker pull zelon88/hrconvert2:v3.7.2
docker run -d --name hrconvert2 \
-p 127.0.0.1:8080:80 \
--security-opt seccomp=unconfined \
zelon88/hrconvert2:v3.7.2docker ps
curl -I http://127.0.0.1:8080/Container hoạt động bình thường sẽ ở trạng thái Up và curl trả về HTTP/1.1 200 OK. Container liên tục restart cho thấy có vấn đề khi startup, vì vậy hãy đọc docker logs hrconvert2 trước khi thay đổi bất kỳ thứ gì khác.
Có 2 flag cần lưu ý. -p 127.0.0.1:8080:80 chỉ publish port trên loopback, nên không có lưu lượng nào đến được converter cho đến khi bạn chủ động đặt proxy phía trước. Ví dụ của project map -p 8080:80 -p 8443:443, khiến service listen trên mọi interface, kể cả interface public. Cần có --security-opt seccomp=unconfined vì bubblewrap tạo sandbox bằng user namespace và các system call mount mà profile seccomp mặc định của Docker chặn lại. Không có flag này, quá trình convert sẽ fail và ứng dụng sẽ cho biết lý do: A sandbox blocks the required syscalls unless it was started with the correct options.
Flag đó có đánh đổi thực sự. Bạn nới lỏng bộ lọc syscall của container để ứng dụng có thể tự tạo sandbox chặt hơn bên trong container. Hai setting quyết định hành vi là $RequireSandbox và $RequireSandboxOnDocker trong Resources/config.php, có giá trị mặc định lần lượt là TRUE và FALSE. Vì yêu cầu Docker mặc định đang tắt, container không có seccomp flag vẫn có thể convert mà hoàn toàn không có sandbox. Khi đã thêm flag, hãy đặt $RequireSandboxOnDocker = TRUE; để khôi phục hành vi từ chối bên trong container.
Nếu máy này chưa có Docker, hãy thiết lập daemon trước. Chạy Docker trên VPS trình bày cách cài đặt, storage driver và cách Docker tự thêm các firewall rule của nó.
Thay vào đó, cài đặt trên Apache và PHP
File Documentation/INSTALLATION_INSTRUCTIONS.txt trong repository là tài liệu chuẩn và gồm 9 bước. Đây là cấu trúc của file. Trước tiên cài web server, ngôn ngữ và sandbox:
sudo apt update
sudo apt install -y apache2 php libapache2-mod-php php-all-dev php8.3-zip php8.3-gd bubblewrapTên php8.3-* tương ứng với Ubuntu 24.04. Chạy php -v và dùng prefix phù hợp với phiên bản của bạn, vì tên package này thay đổi theo từng bản phát hành PHP. Dùng sai tên sẽ gây ra Unable to locate package.
Tiếp theo là các bộ chuyển đổi. Danh sách này bao phủ tài liệu, hình ảnh, audio, video và OCR, tức phần lớn các loại chuyển đổi thực tế:
sudo apt install -y imagemagick ffmpeg libreoffice-common libreoffice-java-common \
default-jre ghostscript poppler-utils libgxps-utils tesseract-ocr inkscape \
xvfb clamav curl tar libxcb-cursor0Archive format, model 3D, ebook và ISO image boot được cần nhiều package hơn danh sách này. Một số package nằm trong component multiverse của Ubuntu. Bước 3 và bước 5 trong hướng dẫn chính thức có đầy đủ danh sách theo đúng thứ tự. Có 2 dependency không phải apt package: repository cung cấp Documentation/Build/ffmpeg-build.sh và Documentation/Build/build-imagemagick-v7.sh cho những ai cần encoder hoặc ImageMagick 7 mà Ubuntu không đóng gói. Hỗ trợ ebook đến từ installer riêng của calibre. Hướng dẫn cung cấp installer này trên một dòng:
sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdinĐây là vendor script được pipe vào shell với quyền root. Đây là phương thức của upstream và không bắt buộc. Bạn có thể bỏ qua; khi đó chỉ mất khả năng chuyển đổi ebook.
Tiếp theo là các giới hạn của PHP. Quá trình chuyển đổi chậm và file lớn, nên giá trị mặc định quá thấp. Project đặt các giá trị này trong php.ini:
max_execution_time = 1200
max_input_time = 90
memory_limit = 512M
post_max_size = 5000M
upload_max_filesize = 5000M
max_file_uploads = 100
display_errors = Off
zlib.output_compression = OnCác con số này giả định máy còn đủ tài nguyên. Hãy giảm chúng trước khi chạy trên VPS nhỏ, vì upload_max_filesize = 5000M cùng với max_file_uploads = 100 mô tả một request duy nhất có thể ghi nhiều dữ liệu hơn sức chứa của disk 40 GB. Restart Apache và xác nhận PHP thực sự đã nạp các giá trị nào:
sudo service apache2 restart
php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"Tiếp theo là working directory. $ConvertLoc trong Resources/config.php dùng để khai báo thư mục này, và giá trị mặc định là /DATA/HRConvert2. Web server user phải sở hữu thư mục đó:
sudo mkdir -p /DATA/HRConvert2
sudo chmod -R 0755 /DATA/HRConvert2
sudo chown -R www-data:www-data /DATA/HRConvert2Giải nén release bên dưới Apache document root. Layout mặc định đặt ứng dụng trong thư mục HRProprietary/HRConvert2, và $InstLoc trong Resources/config.php phải trỏ đến đúng vị trí bạn đã chọn. Sau đó chạy diagnostic tích hợp sẵn. Đây là cách nhanh nhất để phát hiện dependency bị thiếu trước khi người dùng gặp lỗi:
sudo php /path/to/HRConvert2/convertCore.php -v-v kiểm tra toàn bộ quá trình cài đặt: phiên bản core, dependency, trạng thái sandbox và language pack. Không hỗ trợ chuyển đổi file từ command line, nên bộ argument này chỉ dùng cho mục đích quản trị.
Vì sao mọi lần chuyển đổi đều thất bại trên Ubuntu 24.04 mới cài?
Do sandbox. Đây là vấn đề phổ biến nhất trong ngày đầu cài đặt. Ubuntu 24.04 và Debian 12 mặc định hạn chế user namespace của người dùng không có đặc quyền. Bubblewrap cần user namespace để tạo sandbox, nên bwrap không thể khởi động. Ứng dụng từ chối chuyển đổi nếu không có sandbox, vì vậy mọi job đều thất bại.
Kiểm tra trực tiếp:
bwrap --ro-bind / / --dev /dev /bin/true && echo sandbox okLỗi permission denied nghĩa là namespace đã bị chặn. Cách khắc phục là tạo AppArmor profile cho binary bwrap. Trước tiên, liệt kê các file ABI và ghi lại số lớn nhất hiện có:
ls /etc/apparmor.d/abi/Sau đó ghi /etc/apparmor.d/bwrap, thay 4.0 bằng số lớn nhất đó:
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}Nạp profile:
sudo apparmor_parser -r /etc/apparmor.d/bwrapKhông có output nghĩa là profile đã được nạp. Chạy lại kiểm tra bwrap. Kết quả phải là sandbox ok. Từ thời điểm đó, các lần chuyển đổi sẽ hoạt động.
Một converter public là một parser được expose cho người lạ
Đây là lý do phần còn lại của bài viết này tồn tại. Một file converter có thể truy cập từ Internet sẽ nhận file bất kỳ từ một người dùng ẩn danh rồi chuyển file đó cho LibreOffice, ImageMagick, FFmpeg hoặc Ghostscript. Đây đều là các codebase C và C++ lớn, có lịch sử lâu dài về lỗi parser. Người upload chọn format, nghĩa là họ cũng chọn parser nào sẽ chạy và code path nào bên trong parser đó được thực thi.
HRConvert2 xử lý việc này bằng cách chạy mọi dependency bên trong một namespace của bubblewrap. Mỗi lần conversion chỉ nhìn thấy 2 thư mục: thư mục chứa input được mount ở chế độ read only và thư mục nhận output. Network không được share. Theo cách diễn đạt của dự án, closes every URL handler in every dependency at once. Điều này quan trọng hơn nhiều so với tưởng tượng ban đầu. ImageMagick và Ghostscript đều chấp nhận các reference dùng để fetch một URL. Vì vậy, converter có thể biến thành công cụ server side request forgery (SSRF), dùng để truy cập cloud metadata endpoint từ bên trong network của bạn. Khi namespace không có network, việc fetch không thể xảy ra.
Việc từ chối xử lý là nửa còn lại: A server that cannot build a sandbox refuses the conversion rather than quietly running without one. Một tool fail closed có giá trị hơn tool chỉ ghi cảnh báo vào một log mà không ai đọc. Đây cũng là lý do bước cấu hình AppArmor ở trên không phải tùy chọn, và vì sao $RequireSandboxOnDocker cần được xem xét trước khi bạn expose container.
Tăng cường bảo vệ ImageMagick bằng policy.xml
File policy riêng của ImageMagick là một lớp bảo vệ thứ hai bên dưới sandbox và đáng để cấu hình. Trên Ubuntu 24.04 với ImageMagick 6, file này nằm tại /etc/ImageMagick-6/policy.xml. In policy đang được áp dụng:
identify -list policyProject cung cấp một policy tại Documentation/Build/policy.xml và đây là mẫu cấu hình tốt. Policy này từ chối các coder PS, PS2, PS3, EPS, XPS và MVG, đồng thời từ chối các delegate URL, HTTPS, HTTP và gs, nhưng vẫn cho phép PDF:
<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="MVG" />
<policy domain="delegate" rights="none" pattern="URL" />
<policy domain="delegate" rights="none" pattern="gs" />
<policy domain="coder" rights="read|write" pattern="PDF" />Dòng gs là dòng quan trọng nhất. ImageMagick không tự phân tích PostScript. Nó gọi Ghostscript thông qua shell, và delegate đó là nơi các lỗi remote code execution nổi tiếng của ImageMagick xuất hiện. Từ chối delegate này để ImageMagick hoàn toàn không chuyển file được upload cho gs, bất kể file tự nhận là định dạng gì.
Policy tương tự cũng đặt giới hạn tài nguyên. Đây là cách ngăn một image được tạo thủ công ăn hết tài nguyên của máy:
<policy domain="resource" name="memory" value="256MiB"/>
<policy domain="resource" name="map" value="512MiB"/>
<policy domain="resource" name="disk" value="1GiB"/>
<policy domain="resource" name="width" value="16KP"/>
<policy domain="resource" name="height" value="16KP"/>
<policy domain="resource" name="area" value="128MP"/>Decompression bomb là file rất nhỏ nhưng khai báo kích thước khổng lồ. Các giới hạn width, height và area từ chối file trước khi cấp phát tài nguyên, vì vậy process sẽ thoát thay vì để kernel kill một process khác.
Chiều ngược lại cũng có một vấn đề cần lưu ý. Policy mặc định của Ubuntu từ chối hoàn toàn coder PDF, nên trên hệ thống chưa chỉnh sửa, thao tác với PDF sẽ lỗi với attempt to perform an operation not allowed by the security policy 'PDF'. Chuỗi này cho biết policy đang hoạt động đúng. Nếu cho phép coder này hoạt động lại, bạn phải chủ động quyết định và vẫn giữ delegate gs ở trạng thái bị từ chối.
Chi phí của chuỗi dependency trên một VPS nhỏ
Khi idle, các thành phần này hầu như không tốn tài nguyên. Apache và PHP chỉ dùng vài chục megabyte, còn các binary converter hoàn toàn không chạy. Toàn bộ chi phí xuất hiện cùng lúc khi có file được tải lên.
Quá trình chuyển đổi tài liệu khởi động LibreOffice, rồi LibreOffice khởi động Java runtime. Chuyển đổi ảnh cấp cho ImageMagick 256 MiB memory và thêm một memory map 512 MiB theo policy ở trên. Chuyển đổi video cấp cho FFmpeg mọi core hiện có, vì đó là cách FFmpeg xử lý video. memory_limit của PHP được cấu hình là 512M trong project. Các con số này cộng dồn trong một job, bên cạnh operating system và web server.
Vì vậy, một VPS 1 GB sẽ bắt đầu dùng swap ngay từ tài liệu thực tế đầu tiên, sau đó rơi vào tình trạng thrashing. Khi hết memory, kernel out of memory killer sẽ dừng process có resident size lớn nhất. Thường đó là soffice.bin, và người dùng chỉ thấy quá trình chuyển đổi thất bại mà không có thông báo hữu ích. Đôi khi đó là apache2, khiến toàn bộ site ngừng hoạt động. Sau đó dùng dmesg -T | grep -i "killed process" để xác nhận.
Đây là hướng dẫn sizing, không phải benchmark: 4 GB RAM và 2 core là đủ thoải mái cho một team nhỏ, còn 2 GB cùng một swap file vẫn hoạt động nếu tải chủ yếu là tài liệu và ảnh và bạn chấp nhận thời gian chờ. Swap file không làm quá trình chuyển đổi nhanh hơn. Nó biến một đợt tải tăng đột biến thành tình trạng chậm thay vì lỗi nghiêm trọng. Đây là khác biệt giữa một page bị treo và một outage. Hãy dành cho disk nhiều dung lượng hơn mức bạn nghĩ là cần thiết, vì image 3 GB, upload limit lớn và output đã chuyển đổi sẽ cùng nhau làm đầy disk từ lâu trước khi các tài nguyên khác cạn.
Các quá trình chuyển đổi vốn tạo tải theo từng đợt. Hai người cùng upload video sẽ dùng hết mọi core, và request tiếp theo phải chờ phía sau. Phía trước hệ thống này không có job queue, nên giới hạn là biện pháp kiểm soát duy nhất bạn có.
Đặt các giới hạn để một lần upload không làm đầy disk
Trước tiên, giảm các giá trị PHP. Có thể bắt đầu với upload_max_filesize = 512M, post_max_size = 512M và max_file_uploads = 20 cho một máy 4 GB dùng chung. Lưu ý rằng max_execution_time = 1200 cho phép một request PHP chạy trong hai mươi phút. Thời gian này thực sự cần thiết cho một lần chuyển đổi video dài. Điều đó cũng có nghĩa là một lần upload chậm sẽ giữ một worker trong hai mươi phút.
Sau đó, giới hạn kích thước và tốc độ tại proxy, trước khi request đến được PHP:
limit_req_zone $binary_remote_addr zone=convert:10m rate=6r/m;
server {
listen 443 ssl;
server_name convert.example.com;
client_max_body_size 512M;
client_body_timeout 300s;
location / {
limit_req zone=convert burst=4 nodelay;
proxy_pass http://127.0.0.1:8080;
proxy_read_timeout 1200s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}client_max_body_size phải ít nhất bằng kích thước của file lớn nhất mà bạn muốn chuyển đổi. Nếu không, nginx sẽ trả về 413 Request Entity Too Large và PHP không bao giờ nhận được upload. proxy_read_timeout phải dài hơn thời gian chuyển đổi lâu nhất. Nếu không, một job vẫn đang chạy bình thường phía sau proxy sẽ trả về 504 Gateway Time-out cho trình duyệt. Phần còn lại của server block, bao gồm TLS (transport layer security) termination, được trình bày trong giải thích từng dòng cấu hình nginx reverse proxy.
Xóa các file đã chuyển đổi
Mỗi lần chuyển đổi đều để lại một bản sao của file nhạy cảm trong thư mục mà web server có thể đọc. Dọn dẹp là điểm phân biệt một công cụ chuyển đổi với một kho lưu trữ mọi thứ mà bất kỳ ai từng chuyển đổi trên đó.
$DeleteThreshold trong Resources/config.php là thời gian tính bằng phút trước khi một session hết hạn và mặc định là 60. Hạ giá trị này xuống 15 khi nội dung nhạy cảm. Việc quét được thực hiện bằng một đối số dòng lệnh của core:
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c=15-c xóa các session đã hết hạn khỏi cả hai vị trí dữ liệu theo ngưỡng đã cấu hình. -c=15 chỉ dùng 15 phút cho lần chạy đó. -c=now xóa mọi session bất kể tuổi, kể cả session mà user đang dùng để chuyển đổi tại thời điểm đó, vì vậy chỉ dùng nó cho công tác bảo trì. Các đối số tương tự cũng hoạt động bên trong container thông qua docker exec.
Đặt việc quét vào timer để quá trình dọn dẹp không bao giờ phụ thuộc vào việc có người tải một trang. Chỉ cần thêm một dòng vào /etc/cron.d/hrconvert2:
*/10 * * * * www-data php /path/to/HRConvert2/convertCore.php -cVài phút sau, kiểm tra bằng ls /DATA/HRConvert2 và theo dõi các thư mục session cũ biến mất. Vì user của web server sở hữu thư mục đó, đây chính là account mà một parser bị khai thác sẽ có được quyền sử dụng. Do đó account này không nên sở hữu bất kỳ tài nguyên nào khác đáng giá. Account user theo nguyên tắc đặc quyền tối thiểu trên VPS là mô hình tổng quát và đặc biệt phù hợp trong trường hợp này.
Đặt authentication phía trước, trừ khi mục tiêu là public
Bản cài đặt mặc định không có account nào. Đây là thiết kế có chủ đích. Bất kỳ ai truy cập được vào trang đều có thể upload file và chạy các binary converter của bạn. Rate limit chỉ làm chậm việc đó. Vì vậy, hãy xác định bạn đang ở tình huống nào.
Nếu chỉ dùng cho bạn và một vài đồng nghiệp, đừng expose nó ra ngoài. Bind container vào loopback như ở trên và truy cập qua private network hoặc SSH tunnel. Khi đó, không gì trên public Internet có thể gửi file vào service. Cách này loại bỏ toàn bộ attack surface thay vì chỉ filter request. Nếu các đồng nghiệp cần mở trang bằng browser mà bạn không muốn publish hostname hoặc mở port, chạy nó dưới dạng v3 onion service sẽ giữ converter bind vào loopback và vẫn cung cấp cho họ một address để truy cập.
Nếu bắt buộc phải truy cập được từ browser, hãy đặt authentication phía trước proxy. Basic auth chỉ cần 2 command và giúp form upload không bị người lạ truy cập:
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd alicelocation / {
auth_basic "Converter";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:8080;
}Reload nginx rồi mở trang. Nếu xuất hiện prompt thì authentication đang hoạt động. Nếu không có prompt, block location bạn đã sửa không phải block đang xử lý request. Nếu cần account riêng thay vì dùng chung một password, hãy terminate authentication tại một nhà cung cấp single sign-on: một Authentik SSO server tự host cung cấp forward authentication phía trước một application không có login riêng.
Nếu mục tiêu thực sự là một converter public, hãy chấp nhận các hệ quả và lập kế hoạch tương ứng. Giả định rằng sandbox sẽ bị probe. Giữ image tag ở phiên bản cố định, giữ policy của ImageMagick ở mức chặt chẽ, đặt giới hạn upload nhỏ và chạy service trên một VPS không chứa dữ liệu hoặc service quan trọng khác.
Các lỗi thường gặp và chuỗi thông báo bạn sẽ thấy
Mọi lần chuyển đổi đều thất bại ngay lập tức. Sandbox không thể được tạo. Trên bản cài đặt thông thường, nguyên nhân là profile AppArmor. Trong Docker, nguyên nhân là thiếu --security-opt seccomp=unconfined. Ứng dụng nêu rõ điều này: A sandbox blocks the required syscalls unless it was started with the correct options. và trỏ đến See --Require Sandbox-- & --Require Sandbox On Docker-- in config.php.
Chỉ chuyển đổi image thất bại. Bubblewrap is missing or non functional, so this image conversion cannot be isolated! nghĩa là bwrap không tồn tại hoặc không thể truy cập qua PATH mà user của web server có.
Một format thất bại còn các format khác vẫn hoạt động. Đây là binary bị thiếu, được báo rõ ràng: ImageMagick may not be installed, or may not be reachable on the system path used by the web server user. Thông báo tương tự cũng áp dụng cho FFmpeg và LibreOffice. Chạy convertCore.php -v để xem bản cài đặt tìm thấy gì, và nhớ rằng PATH của Apache worker không phải PATH của login shell.
Xử lý PDF thất bại với lỗi policy. attempt to perform an operation not allowed by the security policy 'PDF' xuất phát từ policy.xml của ImageMagick, không phải từ HRConvert2.
Upload lớn trả về lỗi 413. client_max_body_size của nginx nhỏ hơn kích thước file. Chuỗi xử lý có 3 giới hạn: 1 trong nginx và 2 trong PHP. Giới hạn nhỏ nhất sẽ có hiệu lực.
Quá trình chuyển đổi dừng lại dù không có gì rõ ràng thay đổi. The device where data is stored has an insufficient amount of storage space available. Kiểm tra dung lượng trống và xác nhận cleanup sweep thực sự đang chạy.
Cleanup ghi cảnh báo trong log. Could not clean the temporary location! và Could not clean the convert location! là lỗi ownership. User của web server phải là owner của thư mục được chỉ định bởi $ConvertLoc.
FAQ
Có an toàn không khi đưa một công cụ chuyển đổi file tự host lên Internet?
Chỉ tương đối an toàn nếu bạn coi nó là một parser được mở cho người lạ truy cập. Mỗi upload được chuyển cho LibreOffice, ImageMagick, FFmpeg hoặc Ghostscript xử lý, và người upload có thể chọn công cụ được dùng. HRConvert2 chạy các công cụ đó trong namespace của bubblewrap, không có network và chỉ có quyền đọc trên thư mục input. Ứng dụng cũng từ chối mọi thao tác chuyển đổi mà nó không thể sandbox, đây là thiết lập mặc định khá an toàn. Tuy vậy, bạn vẫn nên yêu cầu authentication, đặt giới hạn upload thấp và chạy nó trên một VPS không chứa dữ liệu quan trọng khác.
Vì sao mọi thao tác chuyển đổi đều fail trên bản cài Ubuntu 24.04 mới?
Ubuntu 24.04 và Debian 12 hạn chế user namespace của user không có đặc quyền, trong khi bubblewrap cần một namespace như vậy để tạo sandbox. Vì ứng dụng từ chối chuyển đổi nếu không có sandbox, mọi job đều fail thay vì chỉ một số job fail. Hãy viết AppArmor profile cho /usr/bin/bwrap với flags=(unconfined), load profile bằng sudo apparmor_parser -r /etc/apparmor.d/bwrap, rồi xác nhận bằng bwrap --ro-bind / / --dev /dev /bin/true.
Vì sao chuyển đổi fail trong Docker nhưng chạy được trên bản cài thông thường?
seccomp profile mặc định của Docker chặn các system call mà bubblewrap sử dụng, nên không thể tạo sandbox bên trong container. Hãy khởi động container bằng --security-opt seccomp=unconfined. Đây cũng là lệnh run mà project sử dụng. Lưu ý rằng $RequireSandboxOnDocker mặc định là FALSE, nên container không có flag này có thể chuyển đổi mà hoàn toàn không có sandbox. Hãy đặt giá trị này thành TRUE sau khi đã thêm seccomp flag.
Server chuyển đổi file cần bao nhiêu RAM?
Khi idle, server dùng ít RAM, nhưng một phiên chuyển đổi đang chạy thì không. LibreOffice khởi động Java runtime, ImageMagick dùng 256 MiB memory và một map 512 MiB theo policy được cung cấp, còn giới hạn riêng của PHP là 512M. Trên VPS 1 GB, tổ hợp này gây swap và out of memory killer sẽ dừng soffice.bin hoặc apache2. Hãy dự trù 4 GB và 2 core cho một team nhỏ, đồng thời kiểm tra dmesg -T | grep -i "killed process" mỗi khi một thao tác chuyển đổi kết thúc mà không có thông báo.
File đã chuyển đổi được lưu ở đâu và khi nào bị xóa?
Chúng được lưu trong working directory được chỉ định bởi $ConvertLoc trong Resources/config.php, mặc định là /DATA/HRConvert2. $DeleteThreshold đặt thời gian tính theo phút trước khi một session hết hạn, mặc định là 60. Việc sweep chạy từ command line: php convertCore.php -c xóa các session đã hết hạn, còn -c=now xóa ngay mọi session, kể cả session đang active. Hãy đặt -c trong một cron entry hoặc systemd timer để việc xóa không phụ thuộc vào việc có người truy cập site hay không.