Shlink is a web application built with PHP. It shouldn't be hard to install, but you have to follow these steps.


  • PHP 7.2 or greater with JSON, APCu, intl, curl, PDO and gd extensions enabled.
  • MySQL, PostgreSQL or SQLite.
  • The swoole PHP extension or the web server of your choice with PHP integration (Apache or Nginx).

Install using a dist file

  • Download the latest distributable file and decompress it at the location of your choice
  • Create an empty database (not necessary if you are going to use SQLite).
  • Setup the application by running the bin/install script. It will guide you through the installation process.
  • Recursively grant write permissions to the data directory.
  • Optionally, you can create a symlink to the bin/cli script in a folder which is in your path.
    For example /usr/local/bin for linux systems. This will allow you to easily run shlink from anywhere in the command line.
  • Generate your first API key by running bin/cli api-key:generate. You will need the key in order to interact with shlink's API.
  • Finally access to and configure your server to start creating short URLs.

Install using a docker image

If you want to deploy shlink in a container-based infrastructure, you can just use the official docker image.

Once deployed, you still need to run docker exec -it shlink_container shlink api-key:generate in order to generate the first API key.

Virtual hosts

If you are serving shlink with a web server, you will need to configure the virtual hosts.

These are samples for the most used web servers.

                        server {
    listen 80;
    root /path/to/shlink/public;
    index index.php;
    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;

    location ~ /\.ht {
        deny all;
                        <VirtualHost *:80>
    DocumentRoot "/path/to/shlink/public"

    <Directory "/path/to/shlink/public">
        Options FollowSymLinks Includes ExecCGI
        AllowOverride all
        Order allow,deny
        Allow from all

Shlink with swoole service

If you want to server shlink with swoole, you should create a daemon script, in /etc/init.d/shlink_swoole.

You can use this sample, replacing /path/to/shlink by the path to your shlink installation:

# Provides:          shlink_swoole
# Required-Start:    $local_fs $network $named $time $syslog
# Required-Stop:     $local_fs $network $named $time $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Description:       Shlink non-blocking server with swoole

SCRIPT=/path/to/shlink/vendor/bin/zend-expressive-swoole\ start


start() {
  if [[ -f "$PIDFILE" ]] && kill -0 $(cat "$PIDFILE"); then
    echo 'Shlink with swoole already running' >&2
    return 1
  echo 'Starting shlink with swoole' >&2
  mkdir -p "$LOGDIR"
  touch "$LOGFILE"
  local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
  su -c "$CMD" $RUNAS > "$PIDFILE"
  echo 'Shlink started' >&2

stop() {
  if [[ ! -f "$PIDFILE" ]] || ! kill -0 $(cat "$PIDFILE"); then
    echo 'Shlink with swoole not running' >&2
    return 1
  echo 'Stopping shlink with swoole' >&2
  kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
  echo 'Shlink stopped' >&2

case "$1" in
    echo "Usage: $0 {start|stop|restart}"

Then run these commands to enable the service and start it:

  • sudo chmod +x /etc/init.d/shlink_swoole
  • sudo update-rc.d shlink_swoole defaults
  • sudo update-rc.d shlink_swoole enable
  • /etc/init.d/shlink_swoole start

After that, you should be able to access shlink on port 8080. The service will be automatically run at system start-up, and all access logs will be written in /var/log/shlink/shlink_swoole.log

Long-running tasks

Resolving the IP of a visitor in order to get its location involves performing a request to an external service, which gets time. For this reason, this task is not done in real time.

You can manually run the command visit:process which will process all the IPs from visits.

Alternatively, you could create an scheduled task which automatically runs that command so that the information is updated periodically.

This is an example cron job that could be created under a Unix system. It will run the command every hour, processing all pending IP addresses:

0 * * * * /path/to/shlink/bin/cli visit:process -q

Something similar happens with page previews. Shlink is capable of generating the preview of a page behind a short code by appending the /preview path to a short URL. For example,

If you access that URL, the image will be generated and cached, but the first time, the request will take a little bit more time.

In order to prevent this, you can use the command shortcode:process-previews, which will generate all missing previews so that any later web request is faster

This command can be configured for a cron job too:

30 * * * * /path/to/shlink/bin/cli shortcode:process-previews -q