Shlink is an open-source and self-hosted URL shortener written in PHP. It is used to generate and manage short URLs from the command line. It allows you to track all visits of your short URLs including, location, browser or referrer. It can be integrated with third-party tools using the Shlink API. It provides a command-line interface to shorten URLs.

In this tutorial, I will show you how to install Shlink on Ubuntu 20.04.

Prerequisites

  • A server running Ubuntu 20.04.
  • A valid domain name pointed with your server IP.
  • A root password is configured on the server.

Getting Started

First, update the system packages to the updated version by running the following command:

apt-get update -y

Once all the packages are updated, you can proceed to the next step.

Install LEMP Server

First, install the Nginx, PHP, MariaDB and other required packages with the following command:

apt-get install nginx mariadb-server php-apcu php7.4 php7.4-fpm php7.4-mysql php7.4-gd php7.4-common php7.4-curl php7.4-intl php7.4-gmp php7.4-xml php-dev php-pear unzip -y

Once all the packages are installed, you can proceed to the next step.

Shlink uses MariaDB as a database backend. So you will need to create a database and user for Shlink. First, connect to the MariaDB with the following command:

mysql

Once connected, create a database and user with the following command:

MariaDB [(none)]> CREATE DATABASE shlink;

MariaDB [(none)]> GRANT ALL ON shlink.* TO 'shlink'@'localhost' IDENTIFIED BY 'password';

Next, flush the privileges and exit from the MariaDB with the following command:

MariaDB [(none)]> FLUSH PRIVILEGES;

MariaDB [(none)]> EXIT;

First, download the latest version of Shlink from their official download page:

wget https://github.com/shlinkio/shlink/releases/download/v2.7.1/shlink2.7.1_php7.4_dist.zip

Once the download is completed, unzip the downloaded file with the following command:

unzip shlink2.7.1_php7.4_dist.zip

Next, move the extracted directory to the Nginx web root directory:

mv shlink2.7.1_php7.4_dist /var/www/html/shlink

Next, set proper permission and ownership with the following command:

chown -R www-data:www-data /var/www/html/shlink/

chmod -R 755 /var/www/html/shlink/

Next, run the following command to start the installation:

sudo -u www-data php7.4 /var/www/html/shlink/bin/install

You will be asked to select the database as shown below:

 Welcome to Shlink!!
 This tool will guide you through the installation process.

DATABASE
========

 Select database type [MySQL]:
  [0] MySQL
  [1] MariaDB
  [2] PostgreSQL
  [3] MicrosoftSQL
  [4] SQLite
 > 1

Choose any option and hit Enter. You will be asked to provide the database name as shown below:

 Database name [shlink]:
 > 

Provide your database name or hit Enter to choose default. You will be asked to provide the database host:

 Database host [localhost]:
 > 

Provide your database host or hit Enter to choose the default. You will be asked to provide database port:

 Database port [3306]:
 > 

Provide your database port or hit Enter to choose the default. You will be asked to provide your database username:

 Database username:
 > shlink

Provide your database username and hit Enter. You will be asked to provide your database user password:

 Database password:
 > password

Provide your database user password and hit Enter. You will be asked to provide Unix socket.

 Unix socket (leave empty to not use a socket):
 > 

Leave it empty and hit Enter. You will be asked to provide domain name:

URL SHORTENER
=============

 Default domain for generated short URLs:
 > shlink.linuxbuz.com

Provide your domain name and hit Enter. You will be asked to select the Schema:

 Select schema for generated short URLs [http]:
  [0] http
  [1] https
 > 0

Select an option and hit Enter. You will be asked to validate long URLs:

 Do you want to validate long urls by 200 HTTP status code on response? (yes/no) [yes]:
 > 

Choose the default option and hit Enter. You will be asked to provide the length of the generated shortcodes:

 What is the default length you want generated short codes to have? (You will still be able to override this on every created short URL) [5]:
 > 

Choose default value and hit Enter. You should see the following output:

 Do you want Shlink to resolve the short URL title based on the long URL 's title tag (if any)? Otherwise, it will be kept empty unless explicitly provided. (yes/no) [no]:
 > 

Select default answer and hit Enter. You should see the following output:

 Provide a GeoLite2 license key. (Leave empty to use default one, but it is strongly recommended to get your own. Go to https://shlink.io/documentation/geolite-license-key to know how to get it):
 > 

Leave it empty and hit Enter. You should see the following output:

 What kind of redirect do you want your short URLs to have? [All visits will always be tracked. Not that good for SEO.]:
  [302] All visits will always be tracked. Not that good for SEO.
  [301] Best option for SEO. Redirect will be cached for a short period of time, making some visits not to be tracked.
 > 301

Choose any option and hit Enter. You should see the following output:

 How long (in seconds) do you want your redirects to be cached by visitors? [30]:
 > 

Choose default values and hit Enter. You should see the following output:

TRACKING
========

 Do you want track orphan visits? (visits to the base URL, invalid short URLs or other "not found" URLs) (yes/no) [yes]:
 > 

Choose the default option and hit Enter. You should see the following output:

 Provide a parameter name that you will be able to use to disable tracking on specific request to short URLs (leave empty and this feature won't be enabled):
 > 

Just hit Enter. You should see the following output:

 Do you want to completely disable visits tracking? (yes/no) [no]:
 > 

Choose the default option and hit Enter. You should see the following output:

 Do you want to disable tracking of visitors' IP addresses? (yes/no) [no]:
 > 

Choose the default option and hit Enter. You should see the following output:

 Do you want visitors' remote IP addresses to be anonymized before persisting them to the database? (yes/no) [yes]:
 > 

Choose the default option and hit Enter. You should see the following output:

 Do you want to disable tracking of visitors' "User Agents"? (yes/no) [no]:
 > 

Choose the default option and hit Enter. You should see the following output:

 Do you want to disable tracking of visitors' "Referrers"? (yes/no) [no]:
 > 

Choose the default option and hit Enter. You should see the following output:

REDIRECTS
=========

 Custom URL to redirect to when a user hits Shlink's base URL (If no value is provided, the user will see a default "404 not found" page):
 > http://shlink.linuxbuz.com

Provide your domain name and hit Enter. You should see the following output:

 Custom URL to redirect to when a user hits an invalid short URL (If no value is provided, the user will see a default "404 not found" page):
 > http://shlink.linuxbuz.com

Provide your domain name and hit Enter. You should see the following output:

 Custom URL to redirect to when a user hits a not found URL other than an invalid short URL (If no value is provided, the user will see a default "404 not found" page):
 > http://shlink.linuxbuz.com

Provide your domain name and hit Enter. You should see the following output:

APPLICATION
===========

 Do you want to enable a safety check which will not allow short URLs to be deleted after receiving a specific amount of visits? (yes/no) [yes]:
 > 

Choose the default option and hit Enter. You should see the following output:

 What is the amount of visits from which the system will not allow short URLs to be deleted? [15]:
 > 

Choose the default option and hit Enter. You should see the following output:

 What is the path from which shlink is going to be served? (Leave empty if you plan to serve shlink from the root of the domain) []:
 > 

Choose the default option and hit Enter. You should see the following output:

INTEGRATIONS
============

 Provide a comma-separated list of redis server URIs which will be used for shared caching purposes under shlink multi-instance contexts (Leave empty if you don't want to use redis cache):
 > 

 Custom configuration properly generated!

Initializing database... Success!
Updating database... Success!
Generating proxies... Success!
Downloading GeoLite2 db file... Success!

                                                                                                                        
 [OK] Installation complete!                                                                                                                                                            

Next, you will need to create an Nginx virtual host file for Shlink. You can create it with the following command:

nano /etc/nginx/conf.d/shlink.conf

Add the following lines:

server {
   listen 80;
   server_name shlink.example.com;

   root /var/www/html/shlink/public;
   error_log /var/log/nginx/shlink.error;
   access_log /var/log/nginx/shlink.access;

   index index.php index.html index.htm index.nginx-debian.html;

   location / {
     # try to serve file directly, fallback to app.php
     try_files $uri /index.php$is_args$args;
   }

   # redirect some entire folders
     rewrite ^/(vendor|translations|build)/.* /index.php break;

   location ~ .php$ {
     fastcgi_split_path_info ^(. .php)(/. )$;
     fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;
   }

}

Save and close the file then verify the Nginx for any error with the following command:

nginx -t

You should get the following output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Next, restart the Nginx service to apply the changes:

systemctl restart nginx

You can also verify the status of the Nginx with the following command:

systemctl status nginx

You should get the following output:

? nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2021-06-02 05:28:30 UTC; 4s ago
       Docs: man:nginx(8)
    Process: 25639 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 25653 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 25655 (nginx)
      Tasks: 2 (limit: 2353)
     Memory: 2.6M
     CGroup: /system.slice/nginx.service
             ??25655 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             ??25656 nginx: worker process

Jun 02 05:28:29 ubuntu2004 systemd[1]: Starting A high performance web server and a reverse proxy server...
Jun 02 05:28:30 ubuntu2004 systemd[1]: Started A high performance web server and a reverse proxy server.

You can now install set up Shlink client to short the URL.

You can also generate the Short URL on your server from the command line:

sudo -u www-data php7.4 /var/www/html/shlink/bin/cli short-url:generate

To list all short URLs, run the following command:

sudo -u www-data php7.4 /var/www/html/shlink/bin/cli short-url:list

To display any help information, run the following command:

sudo -u www-data php7.4 /var/www/html/shlink/bin/cli

Conclusion

Congratulations! you have successfully installed Shlink URL shortener on Ubuntu 20.04. You can now short URL using the CLI interface or web-based client.