Shlink URL Shortener
Self-hosted URL shortener with analytics and API.
Overview
Shlink is a powerful, open-source URL shortener developed by Alejandro Celaya that provides comprehensive link management with detailed analytics, QR code generation, and a robust REST API. Unlike simple URL shorteners, Shlink offers enterprise-grade features including geolocation tracking, visit analytics, custom domains, and extensive customization options while maintaining complete control over your data through self-hosting.
This deployment creates a complete Shlink ecosystem using four specialized containers: the main Shlink API server for URL processing and analytics, a dedicated web client for user interface management, PostgreSQL for reliable data persistence, and Redis for high-performance caching and session management. The PostgreSQL database ensures ACID compliance and complex query capabilities for analytics, while Redis provides sub-millisecond response times for frequently accessed short URLs and caching layer optimization.
This stack is ideal for organizations requiring branded short URLs with detailed analytics, marketing teams needing campaign tracking, developers building applications with URL shortening APIs, and privacy-conscious users who want full control over their link data. The combination of Shlink's feature-rich API with PostgreSQL's analytical capabilities and Redis's performance optimization creates a production-ready URL shortening service that scales from personal use to enterprise deployments.
Key Features
- Custom domain support with SSL/HTTPS configuration for branded short URLs
- Comprehensive visit analytics including geolocation, referrer tracking, and device detection
- QR code generation with customizable size and format options for each shortened URL
- REST API with authentication for programmatic URL creation and management
- Real-time visit tracking with Redis-powered caching for instant response times
- PostgreSQL-backed analytics with complex query capabilities for detailed reporting
- Multi-user support with API key management and access control
- URL validation, expiration dates, and maximum visit limits for enhanced control
Common Use Cases
- 1Marketing campaigns requiring detailed click tracking and geographic analytics
- 2SaaS applications needing embedded URL shortening with white-label branding
- 3Enterprise organizations wanting self-hosted alternatives to bit.ly or tinyurl
- 4Social media management tools requiring bulk URL shortening with analytics
- 5E-commerce platforms tracking affiliate and referral link performance
- 6Event management systems generating trackable registration and promotion links
- 7Content creators and bloggers analyzing audience engagement across platforms
Prerequisites
- Docker and Docker Compose installed with at least 2GB available RAM
- Environment variables configured: SHORT_DOMAIN, DB_PASSWORD, API_KEY, GEOLITE_KEY
- GeoLite2 license key from MaxMind for geolocation analytics features
- Ports 8080 and 8081 available for Shlink API and web client access
- Basic understanding of PostgreSQL for database maintenance and backups
- Domain name configured if using custom short domains with DNS records
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 shlink: 3 image: shlinkio/shlink:stable4 container_name: shlink5 environment: 6 - DEFAULT_DOMAIN=${SHORT_DOMAIN}7 - IS_HTTPS_ENABLED=false8 - GEOLITE_LICENSE_KEY=${GEOLITE_KEY}9 - DB_DRIVER=postgres10 - DB_HOST=db11 - DB_NAME=shlink12 - DB_USER=shlink13 - DB_PASSWORD=${DB_PASSWORD}14 - REDIS_SERVERS=redis:637915 ports: 16 - "8080:8080"17 depends_on: 18 - db19 - redis20 networks: 21 - shlink-network22 restart: unless-stopped2324 shlink-web-client: 25 image: shlinkio/shlink-web-client:stable26 container_name: shlink-web-client27 environment: 28 - SHLINK_SERVER_URL=http://localhost:808029 - SHLINK_SERVER_API_KEY=${API_KEY}30 ports: 31 - "8081:80"32 depends_on: 33 - shlink34 networks: 35 - shlink-network36 restart: unless-stopped3738 db: 39 image: postgres:15-alpine40 container_name: shlink-db41 environment: 42 - POSTGRES_USER=shlink43 - POSTGRES_PASSWORD=${DB_PASSWORD}44 - POSTGRES_DB=shlink45 volumes: 46 - postgres-data:/var/lib/postgresql/data47 networks: 48 - shlink-network49 restart: unless-stopped5051 redis: 52 image: redis:7-alpine53 container_name: shlink-redis54 volumes: 55 - redis-data:/data56 networks: 57 - shlink-network58 restart: unless-stopped5960volumes: 61 postgres-data: 62 redis-data: 6364networks: 65 shlink-network: 66 driver: bridge.env Template
.env
1# Shlink2SHORT_DOMAIN=short.example.com3DB_PASSWORD=secure_shlink_password45# Get from maxmind.com for geolocation6GEOLITE_KEY=your_geolite_license_key78# Generate API key: docker exec shlink shlink api-key:generate9API_KEY=your_api_keyUsage Notes
- 1Shlink API at http://localhost:8080
- 2Web client at http://localhost:8081
- 3Generate API key via CLI
- 4QR codes and visit tracking
- 5REST API available
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
shlink
shlink:
image: shlinkio/shlink:stable
container_name: shlink
environment:
- DEFAULT_DOMAIN=${SHORT_DOMAIN}
- IS_HTTPS_ENABLED=false
- GEOLITE_LICENSE_KEY=${GEOLITE_KEY}
- DB_DRIVER=postgres
- DB_HOST=db
- DB_NAME=shlink
- DB_USER=shlink
- DB_PASSWORD=${DB_PASSWORD}
- REDIS_SERVERS=redis:6379
ports:
- "8080:8080"
depends_on:
- db
- redis
networks:
- shlink-network
restart: unless-stopped
shlink-web-client
shlink-web-client:
image: shlinkio/shlink-web-client:stable
container_name: shlink-web-client
environment:
- SHLINK_SERVER_URL=http://localhost:8080
- SHLINK_SERVER_API_KEY=${API_KEY}
ports:
- "8081:80"
depends_on:
- shlink
networks:
- shlink-network
restart: unless-stopped
db
db:
image: postgres:15-alpine
container_name: shlink-db
environment:
- POSTGRES_USER=shlink
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=shlink
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- shlink-network
restart: unless-stopped
redis
redis:
image: redis:7-alpine
container_name: shlink-redis
volumes:
- redis-data:/data
networks:
- shlink-network
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 shlink:5 image: shlinkio/shlink:stable6 container_name: shlink7 environment:8 - DEFAULT_DOMAIN=${SHORT_DOMAIN}9 - IS_HTTPS_ENABLED=false10 - GEOLITE_LICENSE_KEY=${GEOLITE_KEY}11 - DB_DRIVER=postgres12 - DB_HOST=db13 - DB_NAME=shlink14 - DB_USER=shlink15 - DB_PASSWORD=${DB_PASSWORD}16 - REDIS_SERVERS=redis:637917 ports:18 - "8080:8080"19 depends_on:20 - db21 - redis22 networks:23 - shlink-network24 restart: unless-stopped2526 shlink-web-client:27 image: shlinkio/shlink-web-client:stable28 container_name: shlink-web-client29 environment:30 - SHLINK_SERVER_URL=http://localhost:808031 - SHLINK_SERVER_API_KEY=${API_KEY}32 ports:33 - "8081:80"34 depends_on:35 - shlink36 networks:37 - shlink-network38 restart: unless-stopped3940 db:41 image: postgres:15-alpine42 container_name: shlink-db43 environment:44 - POSTGRES_USER=shlink45 - POSTGRES_PASSWORD=${DB_PASSWORD}46 - POSTGRES_DB=shlink47 volumes:48 - postgres-data:/var/lib/postgresql/data49 networks:50 - shlink-network51 restart: unless-stopped5253 redis:54 image: redis:7-alpine55 container_name: shlink-redis56 volumes:57 - redis-data:/data58 networks:59 - shlink-network60 restart: unless-stopped6162volumes:63 postgres-data:64 redis-data:6566networks:67 shlink-network:68 driver: bridge69EOF7071# 2. Create the .env file72cat > .env << 'EOF'73# Shlink74SHORT_DOMAIN=short.example.com75DB_PASSWORD=secure_shlink_password7677# Get from maxmind.com for geolocation78GEOLITE_KEY=your_geolite_license_key7980# Generate API key: docker exec shlink shlink api-key:generate81API_KEY=your_api_key82EOF8384# 3. Start the services85docker compose up -d8687# 4. View logs88docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/shlink-url-shortener/run | bashTroubleshooting
- Shlink container fails to connect to database: Verify DB_PASSWORD matches between shlink and db services, ensure PostgreSQL is fully initialized before Shlink starts
- Web client shows 'Server not accessible': Check SHLINK_SERVER_URL environment variable and ensure shlink container is running on port 8080
- Geolocation data not appearing in analytics: Verify GEOLITE_LICENSE_KEY is valid and MaxMind database downloads are not blocked by firewall
- Redis connection errors in Shlink logs: Confirm redis container is running and accessible on port 6379, check network connectivity within shlink-network
- API key authentication fails: Generate new API key using Shlink CLI command 'bin/cli api-key:generate' inside the shlink container
- Short URLs returning 404 errors: Verify DEFAULT_DOMAIN environment variable matches your intended domain and DNS configuration
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
shlinkshlink-web-clientpostgresqlredis
Tags
#url-shortener#shlink#analytics#links#tracking
Category
Productivity & CollaborationAd Space
Shortcuts: C CopyF FavoriteD Download