Jak zainstalować HRConvert2 na własnym serwerze VPS
Zainstaluj HRConvert2 na własnym serwerze, aby bezpiecznie konwertować pliki bez udziału zewnętrznych serwisów. Instrukcja obejmuje konfigurację Docker, Apache oraz sandbox.
Dlaczego warto samodzielnie hostować konwerter plików
Samodzielnie hostowany konwerter plików pozwala zachować plik na własnym dysku. Jest to jedyny powód, dla którego warto go uruchomić. Darmowe serwisy konwertujące przyjmują przesłany plik, nie dając żadnej gwarancji, co się z nim później dzieje. W przypadku podpisanego kontraktu z klientem lub zeskanowanej dokumentacji medycznej, samo przesłanie pliku stanowi incydent bezpieczeństwa. HRConvert2 to serwer do konwersji plików typu „przeciągnij i upuść”, napisany w PHP i udostępniony na licencji GPLv3. Niniejszy przewodnik został przygotowany dla wersji 3.7.4, wydanej 18 sierpnia 2026 roku. Projekt rozwija się dynamicznie: najnowsza wersja na dzień 13 października 2026 roku to v3.9.1, opublikowana 6 września 2026 roku, a projekt deklaruje obsługę 488 formatów.
Narzędzie nie korzysta z bazy danych, nie posiada kont użytkowników ani plików cookie. Użytkownik jest reprezentowany przez tymczasowy katalog. Każda konwersja jest wykonywana przez lokalne narzędzie wiersza poleceń: LibreOffice dla dokumentów, FFmpeg dla audio i wideo, ImageMagick dla obrazów, Tesseract do optycznego rozpoznawania znaków (OCR) oraz szereg mniejszych narzędzi dla pozostałych formatów. HRConvert2 stanowi stronę przesyłania, potok przetwarzania oraz mechanizm czyszczenia plików.
Narzędzie służy do zmiany formatu pliku. Nie jest to pakiet biurowy w przeglądarce, więc jeśli celem jest edycja dokumentów w karcie przeglądarki, należy rozważyć samodzielnie hostowane OnlyOffice i Collabora. Nie jest to również rozwiązanie do przechowywania danych. Wynik konwersji powinien zostać usunięty, więc jeśli pliki muszą być trwale przechowywane, zadanie to należy powierzyć samodzielnie hostowanemu menedżerowi plików.
Wymagania
System Debian lub Ubuntu, Apache 2.4, PHP 8 lub nowszy oraz bubblewrap. Bubblewrap (bwrap) stanowi środowisko izolowane (sandbox) i jest wymagany: serwer, który nie może utworzyć środowiska izolowanego, odmawia przeprowadzenia konwersji zamiast uruchamiać ją bez zabezpieczeń. Dokumentacja upstream wskazuje, że Raspberry Pi Model B+ jest wystarczający, co odnosi się do części PHP. Pliki binarne konwertera określają rzeczywiste wymagania sprzętowe, co zostało opisane w dalszej części.
Dostępne są dwie metody instalacji. Obraz Docker działa od razu. Instalacja Apache i PHP zajmuje jeden wieczór i pozwala na pełną weryfikację zawartości serwera.
Uruchomienie w nocy przy użyciu Docker
Obraz zawiera wszystkie pliki binarne konwertera, więc jest duży: około 3 GB według stanu na sierpień 2026. Przed pobraniem sprawdź wolne miejsce na dysku.
Tagi mają tutaj znaczenie. Ten przewodnik przypina v3.7.2, który był najnowszym tagiem w Docker Hub w dniu 17 sierpnia 2026 i jednocześnie najnowszym wydaniem w serwisie GitHub tego dnia. Wersja v3.7.4 pojawiła się 18 sierpnia. Według stanu na 13 października 2026 najnowszym wydaniem w serwisie GitHub jest v3.9.1 (6 września 2026), a najnowsze tagi w Docker Hub to edge (22 września 2026) oraz latest, który jest v3.8.4 (31 sierpnia 2026). Tag latest zmienia się dynamicznie, a ta aplikacja posiada rozbudowany parser, dlatego należy przypiąć konkretną wersję i aktualizować ją celowo.
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/Poprawnie działający kontener pozostaje w stanie Up, a curl zwraca HTTP/1.1 200 OK. Kontener, który ciągle się restartuje, ma problem przy starcie, więc przed wprowadzeniem jakichkolwiek zmian przeczytaj docker logs hrconvert2.
Dwie flagi mają kluczowe znaczenie. -p 127.0.0.1:8080:80 publikuje port tylko na interfejsie loopback, więc nic nie dotrze do konwertera, dopóki celowo nie umieścisz przed nim proxy. Obecny przykład projektu mapuje -p 8080:80, który nasłuchuje na każdym interfejsie, w tym publicznym. --security-opt seccomp=unconfined jest wymagane, ponieważ bubblewrap buduje swoją piaskownicę przy użyciu wywołań systemowych user namespace oraz mount, które domyślny profil seccomp w Docker blokuje. Komentarze do wersji 3.7 config.php dodają, że niektóre hosty wymagają również --security-opt apparmor=unconfined. Bez tej flagi konwersje kończą się niepowodzeniem, a aplikacja informuje o przyczynie: A sandbox blocks the required syscalls unless it was started with the correct options.
Ta flaga to istotny kompromis. Rozluźniasz filtr wywołań systemowych kontenera, aby aplikacja mogła zbudować własną, ściślejszą piaskownicę wewnątrz. Dwa ustawienia decydujące o zachowaniu to $RequireSandbox oraz $RequireSandboxOnDocker w pliku Resources/config.php. Wydanie v3.7.4 zawiera je ustawione jako TRUE i FALSE. Przypięty tutaj tag v3.7.2 zawiera oba ustawione jako FALSE, ponieważ komentarze wskazują, że kontener musi mieć wyłączone $RequireSandbox, pozwalając $RequireSandboxOnDocker na podjęcie decyzji. Ponieważ wymaganie Docker jest domyślnie wyłączone, kontener bez flagi seccomp może przeprowadzać konwersję całkowicie bez piaskownicy. Gdy flaga jest aktywna, ustaw $RequireSandboxOnDocker = TRUE;, aby przywrócić zachowanie polegające na odmowie wewnątrz kontenera.
Nowsze obrazy uruchamiają się inaczej. Projekt zmienił proces Docker w wersji v3.8.0 (25 sierpnia 2026). Obecny plik README oraz strona w Docker Hub uruchamiają kontener z --cap-add SYS_ADMIN zamiast opcji seccomp i wskazują, że bez tego konwersje są odrzucane. Jeśli zmienisz przypięcie na tag 3.8 lub 3.9, użyj flag dokumentowanych dla tego obrazu. Ta uprawnienie jest szerokie, więc zachowaj powiązanie portu 127.0.0.1.
Jeśli Docker jest nowy na tej maszynie, najpierw skonfiguruj demona. Uruchamianie Docker na VPS obejmuje instalację, sterownik pamięci masowej oraz sposób, w jaki Docker zapisuje własne reguły zapory sieciowej.
Instalacja na Apache i PHP
Do wersji v3.7.4 plik Documentation/INSTALLATION_INSTRUCTIONS.txt w repozytorium przedstawiał to jako instalację ręczną w dziewięciu krokach, a ta sekcja jest zgodna z tamtym opisem. Od wersji v3.8.0 ten sam plik opisuje zamiast tego skrypt instalacyjny. Uruchomienie sudo bash Documentation/Build/hrconvert2-setup.sh z poziomu sklonowanego repozytorium powoduje zainstalowanie zależności, zapisanie ustawień PHP w pliku typu drop-in zamiast edycji php.ini oraz rozszerzenie profilu AppArmor dla bubblewrap. Następnie php convertCore.php -v i --status weryfikują wynik. Ścieżka ręczna trwa dłużej, ale pozwala dokładnie sprawdzić, co zostało umieszczone na serwerze. Oto jej przebieg. Zacznij od serwera WWW, języka i piaskownicy:
sudo apt update
sudo apt install -y apache2 php libapache2-mod-php php-all-dev php8.3-zip php8.3-gd bubblewrapNazwy php8.3-* odpowiadają Ubuntu 24.04. Uruchom php -v i użyj prefiksu pasującego do posiadanej wersji, ponieważ nazwy pakietów zmieniają się wraz z każdym wydaniem PHP, a użycie błędnych skutkuje Unable to locate package.
Następnie konwertery. Obejmuje to dokumenty, obrazy, dźwięk, wideo oraz OCR, co stanowi większość typowych konwersji:
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-cursor0Formaty archiwów, modele 3D, e-booki i startowe obrazy ISO wymagają większej liczby pakietów, a niektóre z nich znajdują się w komponencie multiverse systemu Ubuntu. W wersji v3.7.4 krok 3 oficjalnej instrukcji zawierał pełną listę apt, a krok 5 budowanie ze źródeł. Obecny przewodnik nie zawiera list pakietów. Instalator odczytuje manifest Resources/Engine/Contract/depends.php, a php convertCore.php --setup --check-depends wyświetla bieżącą listę i jej stan. Dwie zależności można również zbudować ze źródeł. Repozytorium dostarcza Documentation/Build/ffmpeg-build.sh dla koderów, których brakuje w pakietowym FFmpeg, oraz Documentation/Build/build-imagemagick-v7.sh dla ImageMagick 7 na Ubuntu 22.04 lub 24.04, które nadal pakują gałąź 6.9. Ubuntu 25.10 oraz 26.04 LTS zawierają ImageMagick 7.1. Obsługa e-booków pochodzi z instalatora calibre, który w instrukcji 3.7 był podany jako jedna linia:
sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdinJest to skrypt dostawcy przesyłany potokiem do powłoki z uprawnieniami root. Jest to metoda upstream i jest opcjonalna: pominięcie jej powoduje utratę jedynie funkcji konwersji e-booków.
Kolejny krok to limity PHP. Konwersje są powolne, a pliki duże, więc wartości domyślne są zbyt małe. Instrukcja 3.7 ustawiała je w 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 = OnTe liczby zakładają maszynę z odpowiednim zapasem zasobów. Obniż je przed uruchomieniem na małym VPS, ponieważ upload_max_filesize = 5000M z max_file_uploads = 100 opisuje pojedyncze żądanie, które może zapisać znacznie więcej danych, niż mieści dysk 40 GB. Zrestartuj Apache i potwierdź, co faktycznie załadowało PHP:
sudo service apache2 restart
php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"Teraz katalog roboczy. $ConvertLoc w Resources/config.php definiuje jego nazwę, a wartością domyślną jest /DATA/HRConvert2. Użytkownik serwera WWW musi być jego właścicielem:
sudo mkdir -p /DATA/HRConvert2
sudo chmod -R 0755 /DATA/HRConvert2
sudo chown -R www-data:www-data /DATA/HRConvert2Rozpakuj wydanie w katalogu głównym dokumentów Apache. Domyślny układ umieszcza je w folderze HRProprietary/HRConvert2, a $InstLoc w Resources/config.php musi wskazywać miejsce, w którym faktycznie umieszczono pliki. Następnie uruchom wbudowaną diagnostykę, co jest najszybszym sposobem na znalezienie brakującej zależności, zanim zrobi to użytkownik:
sudo php /path/to/HRConvert2/convertCore.php -v-v sprawdza całą instalację: wersje rdzenia, weryfikację zależności, stan piaskownicy i pakiety językowe. Konwersje plików nie są obsługiwane z poziomu wiersza poleceń, więc ten zestaw argumentów służy wyłącznie do celów administracyjnych.
Dlaczego każda konwersja kończy się niepowodzeniem na świeżej instalacji Ubuntu 24.04?
Przyczyną jest piaskownica (sandbox), co stanowi najczęstszy problem pierwszego dnia. Ubuntu 24.04 domyślnie ogranicza nieuprzywilejowane przestrzenie nazw użytkowników (user namespaces) za pomocą AppArmor. Bubblewrap wymaga przestrzeni nazw użytkownika do zbudowania swojej piaskownicy, więc bwrap nie może się uruchomić, a ponieważ aplikacja odmawia konwersji bez piaskownicy, każde zadanie kończy się błędem.
Sprawdź to bezpośrednio:
bwrap --ro-bind / / --dev /dev /bin/true && echo sandbox okBłąd odmowy uprawnień (permission denied) oznacza, że przestrzeń nazw została zablokowana. Rozwiązaniem jest profil AppArmor dla pliku binarnego bwrap. Najpierw wyświetl listę plików ABI i zanotuj najwyższą obecną liczbę:
ls /etc/apparmor.d/abi/Następnie utwórz /etc/apparmor.d/bwrap, zastępując 4.0 tą najwyższą liczbą:
abi <abi/4.0>,
include <tunables/global>
profile bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/bwrap>
}Załaduj profil:
sudo apparmor_parser -r /etc/apparmor.d/bwrapBrak komunikatu wyjściowego oznacza, że profil został załadowany. Uruchom ponownie test bwrap; powinien on wyświetlić sandbox ok. Od tego momentu konwersje będą działać.
Debian 12 nie ma tego problemu. Jego jądro zezwala na nieuprzywilejowane przestrzenie nazw użytkowników, a pakiet bubblewrap ustawia kernel.unprivileged_userns_clone na 1 podczas rozruchu, więc powyższy test przechodzi tam bez dodatkowego profilu. W wersji v3.8.0 i nowszych skrypt instalacyjny automatycznie rozszerza profil AppArmor dla bubblewrap w danej dystrybucji.
Publiczny konwerter to parser udostępniony osobom z zewnątrz
To jest sekcja, dla której powstał cały ten wpis. Konwerter plików dostępny z poziomu Internetu przyjmuje dowolny plik od anonimowego użytkownika i przekazuje go do LibreOffice, ImageMagick, FFmpeg lub Ghostscript. Są to rozbudowane bazy kodu C i C++, posiadające długą historię błędów w parserach. Osoba przesyłająca plik wybiera format, co oznacza, że wybiera również parser, który zostanie uruchomiony, oraz ścieżkę wykonania kodu wewnątrz niego.
Rozwiązaniem HRConvert2 jest uruchamianie każdej zależności wewnątrz przestrzeni nazw bubblewrap. Każda konwersja widzi dwa katalogi: ten zawierający plik wejściowy, zamontowany w trybie tylko do odczytu, oraz ten, do którego trafia wynik. Sieć jest odizolowana, co, jak podaje projekt, closes every URL handler in every dependency at once. Ma to większe znaczenie, niż mogłoby się wydawać. Zarówno ImageMagick, jak i Ghostscript akceptują odwołania pobierające dane z URL, co pozwala przekształcić konwerter w narzędzie do przeprowadzania ataków typu server-side request forgery (SSRF), służące do uzyskania dostępu do punktu końcowego metadanych chmury z wnętrza sieci. Brak dostępu do sieci w przestrzeni nazw uniemożliwia takie pobranie.
Odmowa wykonania operacji to druga połowa zabezpieczeń: A server that cannot build a sandbox refuses the conversion rather than quietly running without one. Narzędzie, które w razie błędu blokuje działanie, jest cenniejsze niż takie, które jedynie wysyła ostrzeżenie do dziennika, którego nikt nie czyta. Jest to również powód, dla którego krok z AppArmor opisany powyżej nie jest opcjonalny, oraz dlaczego warto przyjrzeć się $RequireSandboxOnDocker przed wystawieniem kontenera na zewnątrz.
Wzmocnienie ImageMagick za pomocą policy.xml
Własny plik polityki ImageMagick stanowi drugą warstwę zabezpieczeń pod piaskownicą i warto go skonfigurować. W systemie Ubuntu 24.04 z ImageMagick 6 plik ten znajduje się w /etc/ImageMagick-6/policy.xml. Wyświetl aktualnie aktywną konfigurację:
identify -list policyProjekt dostarcza przykładową politykę w Documentation/Build/policy.xml, która stanowi dobry wzorzec. Blokuje ona koderzy PS, PS2, PS3, EPS, XPS oraz MVG, a także delegaty URL, HTTPS, HTTP i gs, zezwalając jednocześnie na 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" />Linia gs jest kluczowa. ImageMagick nie analizuje samodzielnie formatu PostScript. Wywołuje on zewnętrzny proces Ghostscript i to właśnie w tym delegacie występują znane luki umożliwiające zdalne wykonanie kodu (RCE) w ImageMagick. Zablokowanie tego delegata sprawia, że ImageMagick w ogóle nie przekaże przesłanego pliku do gs, niezależnie od tego, za co plik się podaje.
Ta sama polityka ustala limity zasobów, co zapobiega sytuacji, w której specjalnie przygotowany obraz wyczerpuje zasoby maszyny:
<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"/>Bomba dekompresyjna to niewielki plik, który deklaruje ogromne wymiary. Limity width, height oraz area odrzucają go przed dokonaniem alokacji, dzięki czemu proces kończy się poprawnie, zamiast zostać zabitym przez jądro systemu.
Istnieje pułapka w drugą stronę. Domyślna polityka Ubuntu całkowicie blokuje koder PDF, więc w nienaruszonym systemie operacje na plikach PDF kończą się błędem attempt to perform an operation not allowed by the security policy 'PDF'. Ten komunikat oznacza, że polityka działa zgodnie z przeznaczeniem. Przywrócenie dostępu do tego kodera jest świadomą decyzją, przy której należy zachować zablokowany delegat gs.
Koszt łańcucha zależności na małym serwerze VPS
W stanie spoczynku żadna z tych usług nie jest kosztowna. Apache i PHP zajmują kilkadziesiąt megabajtów, a pliki binarne konwerterów nie są uruchomione. Cały koszt pojawia się w momencie przesłania pliku.
Konwersja dokumentu uruchamia LibreOffice, który z kolei inicjuje środowisko uruchomieniowe Java. Konwersja obrazu przydziela ImageMagick 256 MiB pamięci oraz mapowanie pamięci o rozmiarze 512 MiB zgodnie z powyższą polityką. Konwersja wideo przydziela FFmpeg wszystkie dostępne rdzenie, ponieważ tak działa FFmpeg przy przetwarzaniu wideo. Własny parametr memory_limit dla PHP jest ustawiony na 512M w konfiguracji projektu. Wartości te sumują się podczas pojedynczego zadania, nakładając się na obciążenie systemu operacyjnego i serwera WWW.
W rezultacie serwer VPS z 1 GB pamięci RAM zaczyna korzystać ze swapu przy pierwszym większym dokumencie, co prowadzi do drastycznego spadku wydajności. Gdy pamięć się wyczerpie, mechanizm out of memory killer jądra systemu kończy proces o największym rozmiarze rezydentnym. Zazwyczaj jest to soffice.bin, a użytkownik otrzymuje komunikat o niepowodzeniu konwersji bez żadnych przydatnych informacji. Czasami jest to apache2, co powoduje awarię całej witryny. Fakt ten można potwierdzić po fakcie za pomocą dmesg -T | grep -i "killed process".
Poniższe wskazówki dotyczące doboru zasobów nie stanowią benchmarku: 4 GB pamięci RAM i dwa rdzenie zapewniają komfortową pracę dla małego zespołu, natomiast 2 GB z plikiem wymiany (swap) wystarczą, jeśli obciążenie stanowią dokumenty i obrazy, a użytkownik akceptuje czas oczekiwania. Plik wymiany nie przyspiesza konwersji. Sprawia jedynie, że nagły wzrost obciążenia jest powolny, a nie krytyczny, co stanowi różnicę między zawieszoną stroną a całkowitą awarią. Należy przydzielić dyskowi więcej miejsca, niż wydaje się to konieczne, ponieważ obraz o rozmiarze 3 GB, wysoki limit przesyłania oraz przekonwertowany plik wyjściowy zapełnią przestrzeń dyskową znacznie szybciej niż jakiekolwiek inne zasoby.
Konwersje mają z natury charakter skokowy. Dwie osoby przesyłające wideo w tym samym czasie wykorzystają wszystkie dostępne rdzenie, a kolejne żądania będą czekać w kolejce. Ponieważ nie ma tu kolejki zadań, jedyną dostępną metodą kontroli są limity.
Ustawienie limitów zapobiegających zapełnieniu dysku przez pojedyncze wysyłanie plików
W pierwszej kolejności należy ograniczyć wartości PHP. Ustawienia takie jak upload_max_filesize = 512M, post_max_size = 512M oraz max_file_uploads = 20 stanowią rozsądny punkt wyjścia dla współdzielonego serwera z 4 GB pamięci RAM. Należy pamiętać, że max_execution_time = 1200 pozwala pojedynczemu żądaniu PHP działać przez dwadzieścia minut, co jest niezbędne przy długotrwałej konwersji wideo, ale oznacza również, że wolne wysyłanie pliku blokuje proces roboczy na dwadzieścia minut.
Następnie należy wymusić limity rozmiaru i czasu trwania na poziomie proxy, zanim żądanie dotrze do 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;
}
}Wartość client_max_body_size musi być co najmniej tak duża, jak największy plik przeznaczony do konwersji, w przeciwnym razie nginx zwróci 413 Request Entity Too Large, a PHP nigdy nie otrzyma przesyłanych danych. Wartość proxy_read_timeout musi przekraczać czas trwania najdłuższej konwersji, inaczej zadanie działające poprawnie za proxy zwróci 504 Gateway Time-out do przeglądarki. Pozostała część tego bloku serwera, w tym terminacja TLS (transport layer security), została omówiona w wyjaśnieniu konfiguracji reverse proxy nginx linia po linii.
Usuwanie przekonwertowanych plików
Każda konwersja pozostawia kopię pliku wrażliwego w katalogu dostępnym dla serwera WWW. Sprzątanie jest tym, co odróżnia konwerter od archiwum wszystkiego, co kiedykolwiek zostało na nim przetworzone.
$DeleteThreshold w Resources/config.php określa czas wygaśnięcia sesji w minutach; wartość domyślna to 60. W przypadku treści wrażliwych należy ją obniżyć do 15. Samo czyszczenie jest argumentem linii poleceń dla rdzenia:
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c
sudo -u www-data php /path/to/HRConvert2/convertCore.php -c=15-c usuwa wygasłe sesje z obu lokalizacji danych, stosując skonfigurowany próg. -c=15 używa wartości piętnastu minut tylko dla tego konkretnego uruchomienia. -c=now usuwa wszystkie sesje niezależnie od ich wieku, włącznie z tą, którą użytkownik aktualnie konwertuje, dlatego należy używać tego polecenia wyłącznie w celach konserwacyjnych. Te same argumenty działają wewnątrz kontenera poprzez docker exec.
Należy dodać zadanie czyszczenia do harmonogramu, aby nie zależało ono od ładowania strony przez użytkownika. Wystarczy wpis w /etc/cron.d/hrconvert2:
*/10 * * * * www-data php /path/to/HRConvert2/convertCore.php -cSprawdź działanie po kilku minutach za pomocą ls /DATA/HRConvert2 i obserwuj, jak stare katalogi sesji znikają. Ponieważ użytkownik serwera WWW jest właścicielem tego katalogu, jest to dokładnie to konto, które przejąłby napastnik w przypadku wykorzystania luki w parserze, dlatego nie powinno ono posiadać żadnych innych cennych zasobów. Konta użytkowników o najniższych uprawnieniach na VPS to ogólny wzorzec, który w tym przypadku ma szczególne zastosowanie.
Zabezpiecz usługę uwierzytelnianiem, chyba że ma być publiczna
Domyślna instalacja celowo nie posiada kont użytkowników. Każdy, kto uzyska dostęp do strony, może przesłać plik i uruchomić pliki binarne konwertera, a limity szybkości (rate limits) jedynie spowalniają takie działania. Należy zatem określić charakter wdrożenia.
Jeśli usługa jest przeznaczona tylko dla Ciebie i kilku współpracowników, nie wystawiaj jej na zewnątrz. Powiąż kontener z interfejsem loopback, jak pokazano powyżej, i uzyskuj do niego dostęp przez sieć prywatną lub tunel SSH. Dzięki temu nikt z publicznego Internetu nie będzie mógł przesłać pliku, co całkowicie eliminuje powierzchnię ataku zamiast ją tylko filtrować. Jeśli współpracownicy muszą otwierać stronę w przeglądarce bez konieczności publikowania nazwy hosta lub otwierania portu, udostępnienie usługi jako v3 onion service pozwoli zachować powiązanie konwertera z interfejsem loopback, zapewniając im jednocześnie dostępny adres.
Jeśli usługa musi być dostępna z poziomu przeglądarki, umieść przed proxy warstwę uwierzytelniania. Basic auth wymaga zaledwie dwóch poleceń i skutecznie chroni formularz przesyłania plików przed niepowołanymi osobami:
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;
}Przeładuj nginx i wczytaj stronę. Pojawienie się monitu oznacza poprawne działanie; brak monitu sugeruje, że edytowany blok location nie obsługuje tego żądania. W przypadku korzystania z indywidualnych kont zamiast współdzielonego hasła, należy zastosować terminację przy użyciu dostawcy SSO: samodzielnie hostowany serwer Authentik SSO umożliwia uwierzytelnianie typu forward przed aplikacją, która nie posiada własnego mechanizmu logowania.
Jeśli celem jest stworzenie w pełni publicznego konwertera, należy zaakceptować wynikające z tego ryzyko i odpowiednio się przygotować. Przyjmij założenie, że środowisko izolowane (sandbox) będzie badane przez osoby trzecie. Utrzymuj przypiętą wersję obrazu (image tag), stosuj restrykcyjną politykę ImageMagick, zachowuj niskie limity przesyłania plików i uruchamiaj usługę na serwerze VPS, na którym nie znajdują się żadne inne istotne dane.
Tryby awarii i komunikaty, które zobaczysz
Każda konwersja kończy się natychmiastowym niepowodzeniem. Nie można zbudować środowiska izolowanego (sandbox). W standardowej instalacji Ubuntu 24.04 przyczyną jest profil AppArmor. W przypiętym obrazie Docker 3.7 przyczyną jest brak --security-opt seccomp=unconfined. Aplikacja nazywa to: A sandbox blocks the required syscalls unless it was started with the correct options. i wskazuje na See --Require Sandbox-- & --Require Sandbox On Docker-- in config.php.
Kończą się niepowodzeniem tylko konwersje obrazów. Bubblewrap is missing or non functional, so this image conversion cannot be isolated! oznacza, że bwrap jest nieobecny lub nieosiągalny w ścieżce (PATH) użytkownika serwera WWW.
Jeden format zawodzi, a reszta działa. Brakujący plik binarny, zgłaszany wprost: ImageMagick may not be installed, or may not be reachable on the system path used by the web server user. Ten sam komunikat dotyczy zarówno FFmpeg, jak i LibreOffice. Uruchom convertCore.php -v, aby sprawdzić, co instalacja jest w stanie wykryć i pamiętaj, że zmienna PATH procesu roboczego Apache nie jest tożsama ze zmienną PATH Twojej powłoki logowania.
Praca z PDF kończy się błędem polityki. attempt to perform an operation not allowed by the security policy 'PDF' pochodzi z pliku policy.xml programu ImageMagick, a nie z HRConvert2.
Duże przesyłane pliki zwracają błąd 413. Dyrektywa client_max_body_size w nginx jest mniejsza niż plik. W łańcuchu istnieją trzy limity: jeden w nginx i dwa w PHP; obowiązuje najmniejszy z nich.
Konwersje zatrzymują się, mimo że nie widać żadnych oczywistych zmian. The device where data is stored has an insufficient amount of storage space available. Sprawdź wolne miejsce oraz czy proces czyszczenia faktycznie działa.
Czyszczenie zgłasza błędy w dzienniku. Could not clean the temporary location! oraz Could not clean the convert location! to problemy z uprawnieniami własności. Użytkownik serwera WWW musi być właścicielem katalogu wskazanego przez $ConvertLoc.
FAQ
Czy wystawienie własnego konwertera plików do Internetu jest bezpieczne?
Jest wystarczająco bezpieczne tylko wtedy, gdy traktuje się go jako parser dostępny dla osób trzecich. Każdy przesłany plik trafia do LibreOffice, ImageMagick, FFmpeg lub Ghostscript, a użytkownik przesyłający wybiera narzędzie. HRConvert2 uruchamia te narzędzia wewnątrz przestrzeni nazw bubblewrap bez dostępu do sieci i z katalogiem wejściowym w trybie tylko do odczytu. Aplikacja odrzuca każdą konwersję, której nie może odizolować w piaskownicy, co stanowi bezpieczne ustawienie domyślne. Mimo to zaleca się wymaganie uwierzytelniania, utrzymywanie niskich limitów przesyłania oraz uruchamianie usługi na serwerze VPS, na którym nie znajdują się żadne inne cenne dane.
Dlaczego każda konwersja kończy się niepowodzeniem na świeżej instalacji Ubuntu 24.04?
Ubuntu 24.04 ogranicza nieuprzywilejowane przestrzenie nazw użytkowników za pomocą AppArmor, a bubblewrap wymaga ich do utworzenia piaskownicy. Ponieważ aplikacja odmawia konwersji bez piaskownicy, każde zadanie kończy się błędem. Należy utworzyć profil AppArmor dla /usr/bin/bwrap za pomocą flags=(unconfined), załadować go poleceniem sudo apparmor_parser -r /etc/apparmor.d/bwrap, a następnie potwierdzić za pomocą bwrap --ro-bind / / --dev /dev /bin/true. Debian 12 domyślnie zezwala na nieuprzywilejowane przestrzenie nazw użytkowników i nie wymaga tego kroku.
Dlaczego konwersje nie działają w Docker, a działają w standardowej instalacji?
Domyślny profil seccomp w Docker blokuje wywołania systemowe używane przez bubblewrap, przez co piaskownica nie może zostać utworzona wewnątrz kontenera. W przypadku obrazu 3.7, do którego odnosi się ten dokument, należy uruchomić go z flagą --security-opt seccomp=unconfined, zgodnie z zaleceniami w config.php dla tego wydania. Od wersji v3.8.0 projekt zaleca stosowanie --cap-add SYS_ADMIN. Należy pamiętać, że $RequireSandboxOnDocker jest domyślnie ustawione na FALSE, więc kontener bez odpowiedniej flagi może przeprowadzać konwersję bez żadnej piaskownicy. Po zastosowaniu flagi seccomp należy ustawić tę wartość na TRUE.
Ile pamięci RAM potrzebuje serwer konwersji plików?
W stanie spoczynku zapotrzebowanie jest niewielkie, ale podczas aktywnej konwersji rośnie. LibreOffice uruchamia środowisko uruchomieniowe Java, ImageMagick zajmuje 256 MiB pamięci oraz 512 MiB mapy pamięci zgodnie z dostarczoną polityką, a limit PHP wynosi 512M. Na serwerze VPS z 1 GB pamięci RAM taka kombinacja powoduje użycie swapu, co prowadzi do zakończenia procesu soffice.bin lub apache2 przez mechanizm out of memory killer. Dla małego zespołu należy zaplanować 4 GB pamięci RAM i dwa rdzenie procesora, a w przypadku nagłego przerwania konwersji bez komunikatu sprawdzić dmesg -T | grep -i "killed process".
Gdzie trafiają przekonwertowane pliki i kiedy są usuwane?
Trafiają one do katalogu roboczego określonego przez $ConvertLoc w Resources/config.php, którego domyślna ścieżka to /DATA/HRConvert2. $DeleteThreshold określa czas wygaśnięcia sesji w minutach; wartość domyślna to 60. Czyszczenie odbywa się z poziomu wiersza poleceń: php convertCore.php -c usuwa wygasłe sesje, a -c=now usuwa wszystkie sesje natychmiast, w tym aktywne. Należy dodać -c do wpisu w cron lub timera systemd, aby usuwanie plików nie zależało od wizyt użytkowników w serwisie.