docker.recipes

Kutt URL Shortener

beginner

Modern URL shortener with custom domains and analytics.

Overview

Kutt is a modern, open-source URL shortener that prioritizes user privacy and customization. Built with Node.js and React, it offers a clean alternative to services like bit.ly or TinyURL, allowing organizations to maintain control over their shortened URLs with custom domains, detailed analytics, and comprehensive API access. Unlike cloud-based services, Kutt can be self-hosted to ensure complete data ownership and privacy compliance. This deployment orchestrates three specialized services: the main Kutt application server handling the web interface and API, a PostgreSQL database for storing URLs and user data with full ACID compliance, and Redis for high-performance caching and session management. The PostgreSQL database ensures data integrity for user accounts, shortened URLs, and click analytics, while Redis accelerates response times by caching frequently accessed links and managing user sessions. This stack is ideal for organizations requiring branded URL shortening with complete data control, marketing teams needing detailed link analytics, and developers building applications that integrate URL shortening functionality. The combination of PostgreSQL's reliability and Redis's speed creates a robust foundation for high-traffic URL shortening workloads while maintaining the flexibility to customize domains, user limits, and administrative controls.

Key Features

  • Custom domain support for branded shortened URLs with full DNS configuration
  • Comprehensive link analytics including click tracking, referrer data, and geographic statistics
  • RESTful API for programmatic URL creation and management with authentication
  • QR code generation for shortened URLs with customizable styling options
  • User management system with registration controls and daily link limits
  • Admin panel for user oversight, link moderation, and system configuration
  • Anonymous link creation support with optional registration requirements
  • PostgreSQL-backed data persistence ensuring ACID compliance for all URL and user data

Common Use Cases

  • 1Corporate marketing campaigns requiring branded short URLs with detailed click analytics
  • 2Social media management teams tracking engagement across multiple platforms
  • 3Developer teams integrating URL shortening into applications via API
  • 4Educational institutions sharing course materials with trackable links
  • 5Event organizers distributing registration and information links with usage metrics
  • 6Privacy-conscious organizations avoiding third-party URL shortening services
  • 7SaaS companies providing URL shortening features to their customers

Prerequisites

  • Minimum 1.5GB RAM to support PostgreSQL database operations and Redis caching
  • Port 3000 available for the Kutt web interface and API access
  • Valid domain name configured for custom URL shortening (optional but recommended)
  • Environment variables configured for database credentials, JWT secrets, and admin emails
  • Basic understanding of PostgreSQL administration for database maintenance
  • SMTP server details if email notifications and user registration features are enabled

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 kutt:
3 image: kutt/kutt:latest
4 container_name: kutt
5 environment:
6 - DB_HOST=db
7 - DB_PORT=5432
8 - DB_NAME=kutt
9 - DB_USER=kutt
10 - DB_PASSWORD=${DB_PASSWORD}
11 - REDIS_HOST=redis
12 - REDIS_PORT=6379
13 - SITE_NAME=Kutt
14 - DEFAULT_DOMAIN=${DEFAULT_DOMAIN}
15 - LINK_LENGTH=6
16 - DISALLOW_REGISTRATION=false
17 - DISALLOW_ANONYMOUS_LINKS=false
18 - USER_LIMIT_PER_DAY=50
19 - ADMIN_EMAILS=${ADMIN_EMAIL}
20 - REPORT_EMAIL=${REPORT_EMAIL}
21 - CONTACT_EMAIL=${CONTACT_EMAIL}
22 - JWT_SECRET=${JWT_SECRET}
23 ports:
24 - "3000:3000"
25 depends_on:
26 - db
27 - redis
28 networks:
29 - kutt-network
30 restart: unless-stopped
31
32 db:
33 image: postgres:15-alpine
34 container_name: kutt-db
35 environment:
36 - POSTGRES_USER=kutt
37 - POSTGRES_PASSWORD=${DB_PASSWORD}
38 - POSTGRES_DB=kutt
39 volumes:
40 - postgres-data:/var/lib/postgresql/data
41 networks:
42 - kutt-network
43 restart: unless-stopped
44
45 redis:
46 image: redis:7-alpine
47 container_name: kutt-redis
48 volumes:
49 - redis-data:/data
50 networks:
51 - kutt-network
52 restart: unless-stopped
53
54volumes:
55 postgres-data:
56 redis-data:
57
58networks:
59 kutt-network:
60 driver: bridge

.env Template

.env
1# Kutt
2DEFAULT_DOMAIN=kutt.example.com
3ADMIN_EMAIL=admin@example.com
4REPORT_EMAIL=report@example.com
5CONTACT_EMAIL=contact@example.com
6DB_PASSWORD=secure_kutt_password
7
8# Generate with: openssl rand -hex 32
9JWT_SECRET=your_jwt_secret

Usage Notes

  1. 1Web UI at http://localhost:3000
  2. 2Register first account
  3. 3Custom domains support
  4. 4Link analytics and QR codes
  5. 5API available

Individual Services(3 services)

Copy individual services to mix and match with your existing compose files.

kutt
kutt:
  image: kutt/kutt:latest
  container_name: kutt
  environment:
    - DB_HOST=db
    - DB_PORT=5432
    - DB_NAME=kutt
    - DB_USER=kutt
    - DB_PASSWORD=${DB_PASSWORD}
    - REDIS_HOST=redis
    - REDIS_PORT=6379
    - SITE_NAME=Kutt
    - DEFAULT_DOMAIN=${DEFAULT_DOMAIN}
    - LINK_LENGTH=6
    - DISALLOW_REGISTRATION=false
    - DISALLOW_ANONYMOUS_LINKS=false
    - USER_LIMIT_PER_DAY=50
    - ADMIN_EMAILS=${ADMIN_EMAIL}
    - REPORT_EMAIL=${REPORT_EMAIL}
    - CONTACT_EMAIL=${CONTACT_EMAIL}
    - JWT_SECRET=${JWT_SECRET}
  ports:
    - "3000:3000"
  depends_on:
    - db
    - redis
  networks:
    - kutt-network
  restart: unless-stopped
db
db:
  image: postgres:15-alpine
  container_name: kutt-db
  environment:
    - POSTGRES_USER=kutt
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=kutt
  volumes:
    - postgres-data:/var/lib/postgresql/data
  networks:
    - kutt-network
  restart: unless-stopped
redis
redis:
  image: redis:7-alpine
  container_name: kutt-redis
  volumes:
    - redis-data:/data
  networks:
    - kutt-network
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 kutt:
5 image: kutt/kutt:latest
6 container_name: kutt
7 environment:
8 - DB_HOST=db
9 - DB_PORT=5432
10 - DB_NAME=kutt
11 - DB_USER=kutt
12 - DB_PASSWORD=${DB_PASSWORD}
13 - REDIS_HOST=redis
14 - REDIS_PORT=6379
15 - SITE_NAME=Kutt
16 - DEFAULT_DOMAIN=${DEFAULT_DOMAIN}
17 - LINK_LENGTH=6
18 - DISALLOW_REGISTRATION=false
19 - DISALLOW_ANONYMOUS_LINKS=false
20 - USER_LIMIT_PER_DAY=50
21 - ADMIN_EMAILS=${ADMIN_EMAIL}
22 - REPORT_EMAIL=${REPORT_EMAIL}
23 - CONTACT_EMAIL=${CONTACT_EMAIL}
24 - JWT_SECRET=${JWT_SECRET}
25 ports:
26 - "3000:3000"
27 depends_on:
28 - db
29 - redis
30 networks:
31 - kutt-network
32 restart: unless-stopped
33
34 db:
35 image: postgres:15-alpine
36 container_name: kutt-db
37 environment:
38 - POSTGRES_USER=kutt
39 - POSTGRES_PASSWORD=${DB_PASSWORD}
40 - POSTGRES_DB=kutt
41 volumes:
42 - postgres-data:/var/lib/postgresql/data
43 networks:
44 - kutt-network
45 restart: unless-stopped
46
47 redis:
48 image: redis:7-alpine
49 container_name: kutt-redis
50 volumes:
51 - redis-data:/data
52 networks:
53 - kutt-network
54 restart: unless-stopped
55
56volumes:
57 postgres-data:
58 redis-data:
59
60networks:
61 kutt-network:
62 driver: bridge
63EOF
64
65# 2. Create the .env file
66cat > .env << 'EOF'
67# Kutt
68DEFAULT_DOMAIN=kutt.example.com
69ADMIN_EMAIL=admin@example.com
70REPORT_EMAIL=report@example.com
71CONTACT_EMAIL=contact@example.com
72DB_PASSWORD=secure_kutt_password
73
74# Generate with: openssl rand -hex 32
75JWT_SECRET=your_jwt_secret
76EOF
77
78# 3. Start the services
79docker compose up -d
80
81# 4. View logs
82docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/kutt-url-shortener/run | bash

Troubleshooting

  • Kutt container fails to start with database connection errors: Ensure DB_PASSWORD environment variable matches POSTGRES_PASSWORD and db service is fully initialized
  • Short URLs return 404 errors: Verify DEFAULT_DOMAIN environment variable matches your actual domain and DNS is properly configured
  • User registration fails silently: Check that ADMIN_EMAILS, REPORT_EMAIL, and CONTACT_EMAIL environment variables are set with valid email addresses
  • Redis connection timeouts causing slow performance: Increase Redis memory limits or check redis container logs for memory pressure warnings
  • JWT authentication errors on login: Regenerate JWT_SECRET environment variable and restart kutt container to refresh authentication tokens
  • PostgreSQL data corruption after container restart: Ensure postgres-data volume has proper permissions and sufficient disk space for database growth

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

Ad Space