Skip to content

Instantly share code, notes, and snippets.

@jk779
Last active January 17, 2024 15:49
Show Gist options
  • Save jk779/41c9224c6f8cf5fc3856f46fbd6a4d6b to your computer and use it in GitHub Desktop.
Save jk779/41c9224c6f8cf5fc3856f46fbd6a4d6b to your computer and use it in GitHub Desktop.
Shlink + docker-compose + Postgres + Cloudflare Tunnels

This docker-compose file sets up a complete Shlink instance, a user-friendly URL shortener tool that supports custom domains.
It combines Shlink with a PostgreSQL database and a Cloudflare tunnel to ensure easy access and heightened security.
In just a few steps, you can create, manage, and secure your own short URLs while keeping everything safely behind Cloudflare's network.

My docker-compose.yml file

Of course, replace YOURDOMAIN.com and set the ENV vars :).

services:
  shlink:
    image: shlinkio/shlink:stable
    restart: unless-stopped
    environment:
      - DEFAULT_DOMAIN=YOURDOMAIN.com
      - GEOLITE_LICENSE_KEY=${GEOLITE_LICENSE_KEY}
      - IS_HTTPS_ENABLED=true
      - INITIAL_API_KEY=${INITIAL_API_KEY}
      - DEFAULT_SHORT_CODES_LENGTH=4
      - DB_DRIVER=postgres
      - DB_USER=postgres
      - DB_PASSWORD=${POSTGRES_PASSWORD}
      - DB_HOST=postgres
    depends_on:
      - postgres

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - shlink-dbdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

  admin:
    image: shlinkio/shlink-web-client:latest
    restart: unless-stopped
    environment: 
      - SHLINK_SERVER_URL=https://YOURDOMAIN.com
      - SHLINK_SERVER_API_KEY=${INITIAL_API_KEY}
      - SHLINK_SERVER_NAME=YOURDOMAIN.com

  cf-tunnel-shlink:
    container_name: cf-tunnel-shlink
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=${TUNNEL_TOKEN}
      
volumes:
  shlink-dbdata:

How to configure cloudflare

i'm assuming you're not totally unfamiliar with cloudflare, the interface for the most part is self explanatory tho.
  1. Create a "Tunnel" in Zero Trust -> Access in Cloudflare. This provides the TUNNEL_TOKEN in the cloudflared-Installation snippet. Remove the sudo apt... stuff and just use the token starting with ay.....
  2. Add the API domain, (e.g. YOURDOMAIN.com) to the "Public Hostnames" and point it to http://shlink:8080.
  3. Add an "Application" in Zero Trust -> Access.
    • Set up an admin hostname for your Shlink frontend, e.g., admin.YOURDOMAIN.com.
    • This application must ensure that only you or authorized individuals can use Shlink to create new links and edit/delete existing ones:
    • For beginners, using the email code is probably the simplest method, while more advanced users might prefer OIDC, for example with auth0.com (free tier).
    • Then, whitelist the email addresses that should have access.
  4. Return to your tunnel and add the admin hostname from the Application, (here: admin.YOURDOMAIN.com), to the Public Hostname section and use http://admin:80 as the service URL. VERY IMPORTANT: While adding this hostname, click on Additional application settings -> Access -> Protect with Access and enable it. Then select the "Application" you created in step 3. DO NOT SKIP THIS STEP, OR YOU WILL RISK EXPOSING YOUR API KEYS.

This should be it :) Try to access your version of https://admin.YOURDOMAIN.com.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment