Kutt URL Shortener
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:latest4 container_name: kutt5 environment: 6 - DB_HOST=db7 - DB_PORT=54328 - DB_NAME=kutt9 - DB_USER=kutt10 - DB_PASSWORD=${DB_PASSWORD}11 - REDIS_HOST=redis12 - REDIS_PORT=637913 - SITE_NAME=Kutt14 - DEFAULT_DOMAIN=${DEFAULT_DOMAIN}15 - LINK_LENGTH=616 - DISALLOW_REGISTRATION=false17 - DISALLOW_ANONYMOUS_LINKS=false18 - USER_LIMIT_PER_DAY=5019 - 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 - db27 - redis28 networks: 29 - kutt-network30 restart: unless-stopped3132 db: 33 image: postgres:15-alpine34 container_name: kutt-db35 environment: 36 - POSTGRES_USER=kutt37 - POSTGRES_PASSWORD=${DB_PASSWORD}38 - POSTGRES_DB=kutt39 volumes: 40 - postgres-data:/var/lib/postgresql/data41 networks: 42 - kutt-network43 restart: unless-stopped4445 redis: 46 image: redis:7-alpine47 container_name: kutt-redis48 volumes: 49 - redis-data:/data50 networks: 51 - kutt-network52 restart: unless-stopped5354volumes: 55 postgres-data: 56 redis-data: 5758networks: 59 kutt-network: 60 driver: bridge.env Template
.env
1# Kutt2DEFAULT_DOMAIN=kutt.example.com3ADMIN_EMAIL=admin@example.com4REPORT_EMAIL=report@example.com5CONTACT_EMAIL=contact@example.com6DB_PASSWORD=secure_kutt_password78# Generate with: openssl rand -hex 329JWT_SECRET=your_jwt_secretUsage Notes
- 1Web UI at http://localhost:3000
- 2Register first account
- 3Custom domains support
- 4Link analytics and QR codes
- 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 file2cat > docker-compose.yml << 'EOF'3services:4 kutt:5 image: kutt/kutt:latest6 container_name: kutt7 environment:8 - DB_HOST=db9 - DB_PORT=543210 - DB_NAME=kutt11 - DB_USER=kutt12 - DB_PASSWORD=${DB_PASSWORD}13 - REDIS_HOST=redis14 - REDIS_PORT=637915 - SITE_NAME=Kutt16 - DEFAULT_DOMAIN=${DEFAULT_DOMAIN}17 - LINK_LENGTH=618 - DISALLOW_REGISTRATION=false19 - DISALLOW_ANONYMOUS_LINKS=false20 - USER_LIMIT_PER_DAY=5021 - 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 - db29 - redis30 networks:31 - kutt-network32 restart: unless-stopped3334 db:35 image: postgres:15-alpine36 container_name: kutt-db37 environment:38 - POSTGRES_USER=kutt39 - POSTGRES_PASSWORD=${DB_PASSWORD}40 - POSTGRES_DB=kutt41 volumes:42 - postgres-data:/var/lib/postgresql/data43 networks:44 - kutt-network45 restart: unless-stopped4647 redis:48 image: redis:7-alpine49 container_name: kutt-redis50 volumes:51 - redis-data:/data52 networks:53 - kutt-network54 restart: unless-stopped5556volumes:57 postgres-data:58 redis-data:5960networks:61 kutt-network:62 driver: bridge63EOF6465# 2. Create the .env file66cat > .env << 'EOF'67# Kutt68DEFAULT_DOMAIN=kutt.example.com69ADMIN_EMAIL=admin@example.com70REPORT_EMAIL=report@example.com71CONTACT_EMAIL=contact@example.com72DB_PASSWORD=secure_kutt_password7374# Generate with: openssl rand -hex 3275JWT_SECRET=your_jwt_secret76EOF7778# 3. Start the services79docker compose up -d8081# 4. View logs82docker 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/kutt-url-shortener/run | bashTroubleshooting
- 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
Components
kuttpostgresqlredis
Tags
#url-shortener#kutt#analytics#custom-domains
Category
Productivity & CollaborationAd Space
Shortcuts: C CopyF FavoriteD Download