How to Deploy and Configure Thumbor on Ubuntu 22.04
Introduction
Thumbor is an application that is capable of resizing, cropping, applying filters, and flipping images. Using Thumbor is very easy because people only need to access the URL of the Thumbor service for manipulating an image.
This guide explains how to install and deploy Thumbor on a Vultr Cloud Compute running on Ubuntu 22.04.
Prerequisites
Deploy a Vultr Cloud Compute running on Ubuntu 22.04.
Create a non-root user with sudo access and log in with SSH.
Update the Ubuntu Server.
Install Thumbor
Thumbor is a Python application and it's best to install via pip in a Python virtual environment. You can install Thumbor via apt, but the packages are only available for older Ubuntu versions.
Update the package information.
$ sudo apt update
Install the Python virtual environment library.
$ sudo apt install python3-venv -y
Install the dependencies of Thumbor.
$ sudo apt install build-essential libssl-dev libffi-dev python3-dev libcurl4-openssl-dev libcairo2-dev libjpeg-progs gifsicle ffmpeg -y
Create a virtual environment.
$ python3 -m venv thumbor-venv
Activate the virtual environment.
$ source thumbor-venv/bin/activate
Install Thumbor.
(thumbor-venv) $ pip install thumbor[all]
Optionally, check that all dependencies of Thumbor have been installed.
(thumbor-venv) $ thumbor-doctor
You'll get the version of Thumbor installed. Then, more importantly, you'll see all compiled extensions and libraries support of Thumbor.
Verifying libraries support...
✅ pycurl is installed correctly.
✅ cairosvg is installed correctly.
Verifying thumbor compiled extensions...
✅ _alpha
✅ _bounding_box
✅ _brightness
✅ _colorize
✅ _composite
✅ _contrast
✅ _convolution
✅ _curve
✅ _equalize
✅ _fill
✅ _nine_patch
✅ _noise
✅ _rgb
✅ _round_corner
✅ _saturation
✅ _sharpen
Verifying extension programs...
✅ jpegtran is installed correctly.
✅ ffmpeg is installed correctly.
✅ gifsicle is installed correctly.
Verifying security...
🎉 Congratulations! No errors found! 🎉
You can also install Thumbor with Docker. First, you must install Docker itself.
$ sudo apt install docker.io -y
Running Thumbor with Docker will be explained in the next section.
Launching Thumbor
To launch Thumbor, you can run the thumbor
command inside the virtual environment:
(thumbor-venv) $ thumbor
The Thumbor application runs in the foreground. By default, it runs on port 8888.
Using Thumbor is as easy as accessing it via URL. Suppose you have an image that you want to resize or apply a filter that is located in this URL: https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
You pass a remote image to Thumbor via URL. Because the port 8888 is not accessible by default to the public, you need to open another SSH session into the server. Once you're inside the server, you can access the image from Thumbor via the URL.
$ wget http://localhost:8888/unsafe/300x200/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg -O small_pic.jpg
The small_pic.jpg
file is the resized version of the Acorus_calamus1.jpg
file. The unsafe
part in the URL means you're using Thumbor in a non-secure way. Everyone can use your Thumbor server. Later in this article, you'll tweak the security setting. The 300x200
part means the modification you want to apply to an image with Thumbor. In this case, you resized the image to the 300-pixel width and the 200-pixel height. After that, you passed the full remote image URL to the URL.
The thumbor
command that you're running now will die if you close the SSH session. To prevent that, you can run it in the background with screen or tmux.
But the proper way to run the thumbor
service is to run it with Supervisor or Systemd.
You can run Thumbor on another port.
(thumbor-venv) $ thumbor -p 8000
If you want to run Thumbor on port 80, you need the sudo
permission. However, you cannot run sudo
inside the Python virtual environment. The solution is to run the thumbor
command outside the Python virtual environment.
Kill the thumbor
command by Ctrl+C. Then deactivate the Python virtual environment.
(thumbor-venv) $ deactivate
Then you can run the thumbor
command with the full path.
$ sudo thumbor-venv/bin/thumbor -p 80
Then make sure you open port the 80 to public by using the iptables
command.
$ sudo /sbin/iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT
This way, you can access Thumbor from outside with a browser using this URL, http://your_server_ip_address/unsafe/300x200/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
. Because you haven't installed HTTPS yet, you need to make sure you access the server with the HTTP protocol. Finally, replace your_server_ip_address
with your real IP address or domain.
To run Thumbor with Docker, you can launch it this way.
$ sudo docker run -p 8888:80 minimalcompact/thumbor
Then you can access Thumbor in port 8888. If you want to access it in port 80, you can map it to port 80.
$ sudo docker run -p 80:80 minimalcompact/thumbor
Basic Usage of Thumbor
You've resized your image to be smaller. But you can flip the image as well using this URL, http://your_server_ip_address/unsafe/-300x-200/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
The -300
part means you flipped the image horizontally. The -200
part means you flipped the image vertically.
You can apply a blurring filter to the image using this URL, http://your_server_ip_address/unsafe/filters:blur(10)/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
There is not the only filter you can use. To make your image gray or black and white, open this URL, http://your_server_ip_address/unsafe/filters:grayscale()/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
You can also combine filters with this URL, http://your_server_ip_address/unsafe/filters:noise(300):round_corner(60,255,255,255)/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
You can also combine the resizing command and the filters using this URL, http://your_server_ip_address/unsafe/400x400/filters:noise(300)/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
Kill Thumbor because you want to configure it and launc it with the configuration file.
Configuration of Thumbor
You can configure the behaviors of Thumbor with a configuration file. First, create a sample configuration file.
$ thumbor-venv/bin/thumbor-config > thumbor_sample.conf
You can read the configuration of Thumbor. It's full of comments.
################################### Logging ####################################
## Logging configuration as json
## Defaults to: None
#THUMBOR_LOG_CONFIG = None
## Log Format to be used by thumbor when writing log messages.
## Defaults to: '%(asctime)s %(name)s:%(levelname)s %(message)s'
#THUMBOR_LOG_FORMAT = '%(asctime)s %(name)s:%(levelname)s %(message)s'
## Date Format to be used by thumbor when writing log messages.
## Defaults to: '%Y-%m-%d %H:%M:%S'
#THUMBOR_LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
################################################################################
################################### Imaging ####################################
## Max width in pixels for images read or generated by thumbor
## Defaults to: 0
#MAX_WIDTH = 0
...
## Result Storage that will be used with the compatibility layer, instead of the
## compatibility result storage. Please only use this if you can't use up-to-
## date result storages.
## Defaults to: None
#COMPATIBILITY_LEGACY_RESULT_STORAGE = None
################################################################################
Edit the settings of Thumbor. Uncomment MAX_WIDTH
and set it to this value.
MAX_WIDTH = 100
This setting means the maximum width of the image you're allowed to read.
Then run the thumbor
command with the configuration file.
$ sudo thumbor-venv/bin/thumbor -p 80 -c thumbor_sample.conf
Open this URL, http://your_server_ip_address/unsafe/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
You'll see the width of the image is much smaller than the height of the image even if you ask for a square image (400x400).
Kill Thumbor and edit the configuration file again. Uncomment FILE_STORAGE_ROOT_PATH
and set it with this value.
FILE_STORAGE_ROOT_PATH = '/tmp/storage'
Then run Thumbor again using the configuration file. Open the same URL, http://your_server_ip_address/unsafe/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
Then kill Thumbor again. You can see Thumbor saves the image in the /tmp/storage
directory.
$ ls /tmp/storage
If you use Thumbor with Docker, you can configure it with environment variables.
$ sudo docker run -p 80:80 -e MAX_WIDTH=100 minimalcompact/thumbor
Security of Thumbor
You noticed that there is the unsafe
part in the URL of your Thumbor URL. What it means is everyone can use your Thumbor service. There is no authorization. Attackers can overwhelm your Thumbor service, especially when they ask your Thumbor to do heavy processing like upscaling images and applying filters.
You can prevent that by signing your image URLs to avoid tampering.
Edit the configuration file and uncomment two settings and set them to these values.
SECURITY_KEY = 'Acorus Calamus Secret Key'
ALLOW_UNSAFE_URL = False
Run the thumbor
command with the configuration file.
$ sudo thumbor-venv/bin/thumbor -p 80 -c thumbor_sample.conf
If you access this URL, http://your_server_ip_address/unsafe/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
, you will get this warning.
2023-01-07 08:05:21 thumbor:WARNING URL has unsafe but unsafe is not allowed by the config: /unsafe/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
To use the Thumbor service, you need to generate the safe URL of the remote image. To generate it, you can use the Python library thumbor
.
$ python3 -m venv generate-safe-url
$ source generate-safe-url/bin/activate
(generate-safe-url) $ pip install libthumbor
Then create a Python script and name it generate_safe_url.py
. Add the following content to it:
from libthumbor import CryptoURL
crypto = CryptoURL(key='Acorus Calamus Secret Key')
encrypted_url = crypto.generate(
width=400,
height=400,
image_url='https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg'
)
print(encrypted_url)
You can see that you used the security key that you saved in the Thumbor configuration file.
Run the script.
(generated-safe-url) $ python generate_safe_url.py
You get the safe URL without the server URL.
/4XITN9gQ72mGQ6GuNMU7g1xIyXI=/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
Append the safe URL to your server IP address to get the complete safe URL, http://your_server_ip_address/4XITN9gQ72mGQ6GuNMU7g1xIyXI=/400x400/https://upload.wikimedia.org/wikipedia/commons/3/37/Acorus_calamus1.jpg
.
The unsafe
part is replaced with the 4XITN9gQ72mGQ6GuNMU7g1xIyXI=
part. For every remote image, that cryptic part will be different. Attackers cannot know it in advance unless they know your security key.
If you use Thumbor with Docker, you can set the security setting this way.
$ sudo docker run -p 80:80 -e SECURITY_KEY='Acorus Calamus Secret Key' -e ALLOW_UNSAFE_URL=False minimalcompact/thumbor
If you don't use Python, there are other libraries that can generate safe URLs for different programming languages. You can explore here.
More Information
To learn more about Thumbor, please see these resources.