Ubuntu Tutorial: Shlink

Shlink is a powerful and self-hosted URL shortener that provides detailed analytics, API access, and QR code generation. Whether you’re managing branded links for marketing campaigns or need a private URL shortener, Shlink offers a robust solution without relying on third-party services.

In this guide, we’ll walk you through deploying Shlink using Docker on Ubuntu 24, ensuring a quick and easy setup. With Docker, you can containerize Shlink, making it easier to deploy, maintain, and scale while keeping dependencies isolated. By the end of this tutorial, you’ll have a fully operational Shlink instance as well as Shlink-Web-UI to manage all your short links.

Start by creating a folder for your app data and, in it, create a file named ‘docker-compose.yml’:

mkdir shlink
cd shlink
nano docker-compose.yml

Copy the configuration below to your file and change the variables at the top of the file. The Geolite license key is optional, but if you provide one, you will get the country from which your users connect. The Shlink server API key will be generated later so you don’t need to change it now.

x-common:
    x-database:
        &db-environment
        MYSQL_PASSWORD: &db-password "CHANGE_ME"
        MYSQL_ROOT_PASSWORD: "CHANGE_ME_TOO"
    x-shlink:
        &shl-environment
        GEOLITE_LICENSE_KEY: "yourlicensehere" # Optional
        DEFAULT_DOMAIN: "yourdomain.example.com"
    x-webui:
        &wui-environment
        SHLINK_SERVER_URL: "http://yourdomain.example.com"
        SHLINK_SERVER_API_KEY: "yourshlinkapihere" # GENERATED LATER
        SHLINK_SERVER_NAME: "yourshlinksvname" # EX: TMVTech_Links

##########################################################

services:
    database:
        image: 'mariadb:11.7'
        restart: unless-stopped
        command: --default-authentication-plugin=mysql_native_password
        environment:
            <<: *db-environment
            MYSQL_DATABASE: "shlink"
            MYSQL_USER: "shlink"
        container_name: shlink-db
        volumes:
            - "./data/database:/var/lib/mysql"
    shlink:
        image: 'shlinkio/shlink:stable'
        restart: unless-stopped
        environment:
            <<: *shl-environment
            DB_USER: "shlink"
            DB_PASSWORD: *db-password
            DB_DRIVER: "mysql"
            DB_HOST: "database"
            IS_HTTPS_ENABLED: true
        ports:
            - '9000:8080'
        container_name: shlink
        depends_on:
            - database
    #webui:
    #    image: 'shlinkio/shlink-web-client:stable'
    #    restart: unless-stopped
    #    environment:
    #        <<: *wui-environment
    #    ports:
    #        - '9001:8080'
    #    container_name: shlink-ui
    #    depends_on:
    #        - shlink

After saving the file (on nano, CTRL+O to save and CTRL+X to exit), run the command below to start your database and Shlink’s containers:

docker compose up -d

If the containers started successfully, run the command below to open a terminal inside the Shlink container:

docker compose exec -it shlink sh

Inside the container, run this command to generate an API key to use in our client:

shlink api-key:generate

Save the API key in a safe place and exit the container terminal:

exit

Now you need to stop the containers so that we can edit the compose file:

docker compose down

Run this command again to edit the ‘docker-compose.yml’ file:

nano docker-compose.yml

At the top of the file change ‘SHLINK_SERVER_API_KEY’ to the one we just generated:

x-common:
    x-database:
        &db-environment
        MYSQL_PASSWORD: &db-password "CHANGE_ME"
        MYSQL_ROOT_PASSWORD: "CHANGE_ME_TOO"
    x-shlink:
        &shl-environment
        GEOLITE_LICENSE_KEY: "yourlicensehere"
        DEFAULT_DOMAIN: "yourdomain.example.com"
    x-webui:
        &wui-environment
        SHLINK_SERVER_URL: "http://yourdomain.example.com"
        SHLINK_SERVER_API_KEY: "yourshlinkapihere" # PASTE TOKEN HERE
        SHLINK_SERVER_NAME: "yourshlinksvname"

At the bottom of the file, uncomment the webui service, save the file and exit nano:

    webui:
        image: 'shlinkio/shlink-web-client:stable'
        restart: unless-stopped
        environment:
            <<: *wui-environment
        ports:
            - '9001:8080'
        container_name: shlink-ui
        depends_on:
            - shlink

Finally, start your containers again:

docker compose up -d

You can now access your dashboard at ‘yourip:9001’, once you are there, you should see your server in a list, click on it:

On this dashboard, you get a summary of what is going on with your links. To create your first short link, click on ‘Create short URI’ in the left bar.

Give it the link, some tags, title and short link. If needed, you can also set a duration so that this link automatically expires.

Back to the dashboard, you should now see your link at the bottom. Try clicking on it!

Using your link should automatically redirect you to the URL you set.

You should now have one visit on your new link:

Clicking on the visit count should also give you some stats about your visitors.

3 - Generating QR Codes

With the Web Client, creating a QR Code is very easy, simply click on the 3 dots icon at the right of one of your short links and click on ‘QR code’:

After changing some of the settings you can then either save the QR Code to your computer, or use it on your website!

The images below are imported using the URL given to us by the QR Code generator above:

QR Code
Link to Song
QR Code
Link to Tiktok
QR Code
Link to Youtube
QR Code
Link to Facebook

And that’s all. Thanks for reading and stay tuned for more tech insights and tutorials. Until next time, and keep exploring the world of tech!