How to Deploy and Configure Thumbor on Ubuntu 22.04

Updated on February 1, 2023
How to Deploy and Configure Thumbor on Ubuntu 22.04 header image

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

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.

  1. Update the package information.

     $ sudo apt update
  2. Install the Python virtual environment library.

     $ sudo apt install python3-venv -y
  3. 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
  4. Create a virtual environment.

     $ python3 -m venv thumbor-venv
  5. Activate the virtual environment.

     $ source thumbor-venv/bin/activate
  6. 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.