Skip to content

Server (Hostinger)

Backups

Backblaze uploads

Uses the b2 cli. Installed in /home/u159938358/domains/shepherdsglobal.org/tools with a custom wrapper script to make it run, since /tmp isn’t accessible on Hostinger.

Add the following to .profile in Hostinger so that the b2 command can be run from anywhere.

export PATH="/home/u159938358/domains/shepherdsglobal.org/tools:$PATH"

And the following cron job to backup the wp-contents folder:

0 23 * * * /home/u159938358/domains/shepherdsglobal.org/tools/backup.sh

QPDF Installation/Use

Copy a link for the latest release from Github. SSH into the Hostinger server, cd to the tools directory

wget https://github.com/qpdf/qpdf/releases/download/v12.2.0/qpdf-12.2.0-bin-linux-x86_64.zip
Unzip it
unzip qpdf-12.2.0-bin-linux-x86_64.zip
Run it

./bin/qpdf

We use QPDF for concatenating Cover/Text PDF files on the server so that we can have one PDF file with cover and text. (It runs via concatenate_covers.sh in the 'files' directory).

We also use QPDF for reversing RTL-language PDF files (via reverse_rtl_files.sh in the 'files' directory). Just run it, and it will process all PDF text files in arabic and urdu folders and save them reversed with a filename of *-rev.pdf.

mkdocs

Create a binary for mkdocs using pyinstaller in a similar environment to the server (CentOS 8).

Here's the command history from start to finish in CentOS 8:

# https://serverfault.com/a/1161847
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS-*.repo
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS-*.repo
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS-*.repo
yum update -y

# https://stackoverflow.com/a/66016318
dnf groupinstall "Development Tools"
yum install openssl-devel libffi-devel bzip2-devel
yum install wget -y
wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz
tar xvf Python-*.tgz
cd Python-3.9*/
./configure --enable-optimizations --prefix=/usr/local --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"
make altinstall
which pip3.9
pip3.9 install wheel
pip3.9 install mkdocs-material
pip3.9 install pyinstaller

# https://github.com/mkdocs/mkdocs/issues/2711#issuecomment-996752763
# https://stackoverflow.com/a/53418707
pyinstaller --clean --noconfirm --hiddenimport material --runtime-tmpdir temp /usr/local/bin/mkdocs --recursive-copy-metadata mkdocs --collect-submodules mkdocs --collect-data mkdocs --collect-all material --collect-all mkdocs --collect-all pymdownx --onefile

Note

If you get errors when running mkdocs build on Hostinger, you'll probably need to add that module that's throwing the error and re-generate the binary using pyinstaller. Just add --collect-all [name_of_module] to the line above. See the pyinstaller docs.

Upload the resultant binary file in the dist directory to the Hostinger server and make it executable: chmod +x mkdocs.

Warning

If when you run the mkdocs binary you get the following error:
"./mkdocs: error while loading shared libraries: libz.so.1: failed to map segment from shared object"
that's because of Hostinger having the /tmp folder locked down. You need to set a new temp folder so that the binary can run properly. (This problem also affects the b2 binary, we had to write a little wrapper script that sets the TMP variable first and then calls the tool.)

It's an easy fix; just run export TMP=temp before running the mkdocs command. Better yet, use the --runtime-tmpdir temp when running pyinstaller to have it automatically use a local "temp" folder, rather than trying to write to system /tmp.

.htaccess Redirects

See the .htaccess file in the root of /public_html. We have a LOT of custom redirects to send old links from the old Wix website going to their proper places.

Click to see the relevent portion of the .htaccess file
.htaccess
# Redirects from old website
RedirectMatch 301 ^/language-downloads/chinese-\(traditional\)$ /courses/traditional-chinese/
RedirectMatch 301 ^/language-downloads/chinese-\(simplified\)$ /courses/simplified-chinese/
RedirectMatch 301 ^/individual-course-info(.*)$ /courses/english/
RedirectMatch 301 ^/team-member-profile/(.*)$ /our-team/
RedirectMatch 301 ^/product-page(.*)$ /courses/english/
RedirectMatch 301 ^/product/(.*)$ /courses/english/
RedirectMatch 301 ^/_files/(.*)$ /courses/english/
RedirectMatch 301 ^/copy-of(.*)$ /courses/english/
RedirectMatch 301 ^/post/(.*)$ /blog/

Redirect 301 /members /
Redirect 301 /sgc-live /
Redirect 301 /who-we-are /
Redirect 301 /give /donate/
Redirect 301 /store /courses/
Redirect 301 /give-now /donate/
Redirect 301 /our-story /about/
Redirect 301 /downloads /courses/
Redirect 301 /courses-new /courses/
Redirect 301 /event-details/vision /
Redirect 301 /supporter-info /contact/
Redirect 301 /course-overviews /courses/
Redirect 301 /blog/categories/ /category/
Redirect 301 /sustaining-members /donate/
Redirect 301 /language-downloads/ /courses/
Redirect 301 /purchase-bundles /courses/english/
Redirect 301 /legal-text/copyright-policy /copyright/
Redirect 301 /legal-text/privacy-policy /privacy-policy/
Redirect 301 "/legal-text/return-policy" "/return-policy/"