Deploying Chhoto URL
Chhoto URL is a lightweight, open-source URL shortening service that enables users to create short, memorable links from long URLs. It provides features like custom aliases, QR code generation, link analytics, expiration dates, and password protection, making it ideal for marketers, developers, and organizations that need a self-hosted alternative to commercial URL shortening services. Chhoto URL gives you complete control over your links without relying on third-party services.
This guide will walk you through deploying Chhoto URL on Klutch.sh, a modern cloud platform that simplifies containerized application deployment. By the end of this guide, you’ll have a fully functional URL shortening service ready for use.
Why Deploy Chhoto URL on Klutch.sh?
Klutch.sh provides an excellent platform for hosting Chhoto URL:
- Docker-native deployment - Klutch.sh automatically detects and deploys Dockerized applications
- Fast and reliable - Serve short URL redirects with minimal latency
- Custom domains - Use your own domain for branded short links
- Environment configuration - Manage secrets and configuration through the dashboard
- Data persistence - Reliable storage for URL mappings and analytics
- Scalability - Easily scale resources as your link volume grows
Prerequisites
Before deploying Chhoto URL on Klutch.sh, you’ll need:
- A Klutch.sh account (sign up for free)
- Access to the Klutch.sh dashboard
- A GitHub repository to store your Chhoto URL deployment configuration
- A custom domain (optional but recommended for branded short links)
- Basic understanding of Docker and containerization
Deployment Steps
Create a Dockerfile
Create a
Dockerfilein the root of your repository to containerize Chhoto URL:FROM node:20-alpine# Install system dependenciesRUN apk add --no-cache \build-base \python3 \git \curl# Set working directoryWORKDIR /app# Clone Chhoto URL repositoryRUN git clone https://github.com/shayneobrien/chhoto-url.git . && \git checkout main# Install dependenciesRUN npm install# Build the applicationRUN npm run build || true# Create necessary directoriesRUN mkdir -p /app/data /app/logs# Expose portEXPOSE 3000# Health checkHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \CMD node -e "require('http').get('http://localhost:3000/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})" || exit 1# Start the applicationCMD ["npm", "start"]Create Environment Configuration File
Create a
.env.examplefile to document required environment variables:# Chhoto URL Environment Configuration# Application SettingsNODE_ENV=productionPORT=3000HOST=0.0.0.0# Database ConfigurationDATABASE_URL=postgresql://chottourl:chottopass@localhost:5432/chottourlDB_HOST=dbDB_PORT=5432DB_NAME=chottourlDB_USER=chottourlDB_PASSWORD=secure_password_change_in_production# Redis Configuration (for caching)REDIS_URL=redis://redis:6379REDIS_DB=0# Application Base URLBASE_URL=https://example-app.klutch.shSHORT_LINK_PREFIX=s# SecurityAPP_SECRET=your-app-secret-change-in-productionJWT_SECRET=your-jwt-secret-change-in-production# Link SettingsDEFAULT_EXPIRATION_DAYS=365MAX_EXPIRATION_DAYS=3650ALLOW_CUSTOM_ALIASES=trueENABLE_QR_CODES=trueENABLE_LINK_PREVIEW=true# File Upload ConfigurationMAX_FILE_SIZE=10485760UPLOAD_DIR=/app/data/uploads# Email Configuration (Optional)SMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_USER=your-email@gmail.comSMTP_PASSWORD=your-app-passwordSMTP_FROM=noreply@example-app.klutch.sh# AuthenticationENABLE_USER_REGISTRATION=trueREQUIRE_EMAIL_VERIFICATION=false# API ConfigurationAPI_ENABLED=trueAPI_RATE_LIMIT=100CORS_ORIGIN=https://example-app.klutch.sh# Admin SettingsADMIN_EMAIL=admin@example.comADMIN_PASSWORD=change-me-in-production# AnalyticsENABLE_ANALYTICS=trueTRACK_IP_ADDRESS=false# LoggingLOG_LEVEL=infoLOG_DIR=/app/logs# Feature FlagsENABLE_API_KEYS=trueENABLE_BULK_SHORTENING=falseENABLE_LINK_EXPIRATION=trueENABLE_LINK_CLICKS_LIMIT=falseCreate Application Configuration File
Create a
config.jsfile for application-specific settings:module.exports = {app: {name: 'Chhoto URL',version: '1.0.0',environment: process.env.NODE_ENV || 'production',port: process.env.PORT || 3000,host: process.env.HOST || '0.0.0.0',baseUrl: process.env.BASE_URL || 'http://localhost:3000',shortLinkPrefix: process.env.SHORT_LINK_PREFIX || 's'},database: {url: process.env.DATABASE_URL,host: process.env.DB_HOST,port: parseInt(process.env.DB_PORT) || 5432,name: process.env.DB_NAME,user: process.env.DB_USER,password: process.env.DB_PASSWORD,pool: {min: 2,max: 10,idleTimeoutMillis: 30000,connectionTimeoutMillis: 2000}},redis: {url: process.env.REDIS_URL,db: parseInt(process.env.REDIS_DB) || 0,retryStrategy: (times) => Math.min(times * 50, 2000),maxRetriesPerRequest: null},security: {appSecret: process.env.APP_SECRET,jwtSecret: process.env.JWT_SECRET,tokenExpiration: '7d'},links: {defaultExpirationDays: parseInt(process.env.DEFAULT_EXPIRATION_DAYS) || 365,maxExpirationDays: parseInt(process.env.MAX_EXPIRATION_DAYS) || 3650,allowCustomAliases: process.env.ALLOW_CUSTOM_ALIASES === 'true',enableQrCodes: process.env.ENABLE_QR_CODES === 'true',enableLinkPreview: process.env.ENABLE_LINK_PREVIEW === 'true'},fileUpload: {maxFileSize: parseInt(process.env.MAX_FILE_SIZE) || 10485760,uploadDir: process.env.UPLOAD_DIR || '/app/data/uploads',allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp']},cors: {origin: process.env.CORS_ORIGIN || 'http://localhost:3000'},auth: {enableUserRegistration: process.env.ENABLE_USER_REGISTRATION === 'true',requireEmailVerification: process.env.REQUIRE_EMAIL_VERIFICATION === 'true'},api: {enabled: process.env.API_ENABLED === 'true',rateLimit: parseInt(process.env.API_RATE_LIMIT) || 100},email: {host: process.env.SMTP_HOST,port: parseInt(process.env.SMTP_PORT) || 587,user: process.env.SMTP_USER,password: process.env.SMTP_PASSWORD,from: process.env.SMTP_FROM || 'noreply@chhoto.local'},logging: {level: process.env.LOG_LEVEL || 'info',dir: process.env.LOG_DIR || '/app/logs'}};Create Database Initialization Script
Create an
init-db.shfile to set up the PostgreSQL database:#!/bin/bashset -eecho "Initializing Chhoto URL database..."# Wait for PostgreSQL to be readyuntil PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -U "$DB_USER" -d "postgres" -c "\q"; doecho 'Waiting for postgres...'sleep 1doneecho "PostgreSQL is ready!"# Create database if it doesn't existPGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -U "$DB_USER" -d "postgres" << EOFCREATE DATABASE $DB_NAME;EOFecho "Database created!"# Run migrationsecho "Running database migrations..."npm run migrate# Seed initial dataecho "Seeding initial data..."npm run seed || trueecho "Database initialization complete!"Make it executable:
Terminal window chmod +x init-db.shCreate Docker Compose for Local Development
Create a
docker-compose.ymlfile for local development and testing (not used for Klutch.sh deployment):version: '3.8'services:chottourl:build: .container_name: chottourl-devports:- "3000:3000"environment:- NODE_ENV=development- DATABASE_URL=postgresql://chottourl:chottopass@db:5432/chottourl- DB_HOST=db- DB_PORT=5432- DB_NAME=chottourl- DB_USER=chottourl- DB_PASSWORD=chottopass- REDIS_URL=redis://redis:6379- BASE_URL=http://localhost:3000- APP_SECRET=dev-secret-change-in-production- JWT_SECRET=dev-jwt-secret-change-in-production- ENABLE_USER_REGISTRATION=true- ENABLE_ANALYTICS=truedepends_on:- db- redisvolumes:- ./data:/app/data- ./src:/app/srcnetworks:- chottourl-networkdb:image: postgres:16-alpinecontainer_name: chottourl-dbenvironment:- POSTGRES_USER=chottourl- POSTGRES_PASSWORD=chottopass- POSTGRES_DB=chottourlvolumes:- chottourl_db_data:/var/lib/postgresql/datanetworks:- chottourl-networkhealthcheck:test: ["CMD-SHELL", "pg_isready -U chottourl"]interval: 10stimeout: 5sretries: 5redis:image: redis:7-alpinecontainer_name: chottourl-redisnetworks:- chottourl-networkhealthcheck:test: ["CMD", "redis-cli", "ping"]interval: 10stimeout: 5sretries: 5volumes:chottourl_db_data:networks:chottourl-network:driver: bridgeCreate .gitignore File
Create a
.gitignorefile to exclude sensitive data from version control:# Environment files.env.env.local.env.*.local# Node.jsnode_modules/npm-debug.logyarn-error.logpackage-lock.jsonyarn.lock# Build artifactsdist/build/.next/out/# Data and uploadsdata/uploads/public/uploads/# Logslogs/*.log# IDE.vscode/.idea/*.swp*.swo*~.DS_Store# Cache.cache/.turbo/# Database*.sqlite*.sqlite3Push Configuration to GitHub
Push your repository to GitHub with all configuration files:
Terminal window git add Dockerfile .env.example config.js init-db.sh \docker-compose.yml .gitignoregit commit -m "Initial Chhoto URL deployment configuration for Klutch.sh"git push origin mainDeploy on Klutch.sh
- Navigate to klutch.sh/app and log in to your dashboard
- Click Create New App
- Connect your GitHub repository containing the Chhoto URL deployment files (the Dockerfile will be automatically detected)
- Configure your application settings:
- Set your preferred app name
- Review the detected Dockerfile configuration
- Select a region for deployment
- Click Deploy to start the deployment process
- Monitor the deployment progress in the dashboard
- Wait for the deployment to complete and your app to become active
Configure Environment Variables
- In your app dashboard, navigate to Environment Variables section
- Add all required variables from your
.env.examplefile:DATABASE_URL: Your PostgreSQL connection stringDB_HOST: Your PostgreSQL hostnameDB_NAME: Database name (chottourl)DB_USER: Database userDB_PASSWORD: Secure database passwordREDIS_URL: Your Redis connection stringBASE_URL: Set tohttps://example-app.klutch.sh(or your custom domain)APP_SECRET: Generate a secure secret withopenssl rand -base64 32JWT_SECRET: Generate a secure JWT secret withopenssl rand -base64 32ADMIN_EMAILandADMIN_PASSWORD: Administrator credentials
- Click Save to apply the environment variables
- Your application will automatically restart with the new configuration
Configure Traffic Routes
- In your app dashboard, navigate to Traffic settings
- Select HTTP as the traffic type
- Set the internal port to 3000 (Chhoto URL Node.js server default)
- Configure any custom domain settings if you have a domain
- Save your traffic configuration
Attach Persistent Volumes
Chhoto URL requires persistent storage for uploaded files, data, and logs.
- In your app dashboard, navigate to Volumes settings
- Click Add Volume to create storage for application data:
- Enter mount path:
/app/data - Set volume size to 20GB (adjust based on expected link volume and analytics data)
- Click Attach to create and mount the volume
- Enter mount path:
- Click Add Volume again for application logs:
- Enter mount path:
/app/logs - Set volume size to 5GB
- Click Attach to create and mount the volume
- Enter mount path:
Your Chhoto URL application will now be accessible at your configured domain or at
example-app.klutch.sh.
Initial Setup and Configuration
After deploying Chhoto URL on Klutch.sh, complete the initial setup to prepare your URL shortening service.
Access Your Chhoto URL Instance
- Navigate to
https://example-app.klutch.shin your web browser - You’ll see the Chhoto URL home page
- Click Admin or navigate to
/adminfor administrator access - Log in with the admin credentials you set in environment variables
- Complete the initial setup wizard
Configure Your Chhoto URL Instance
Once logged in, configure these essential settings:
Site Settings:
- Set your site name and branding
- Configure the short link base URL (your domain)
- Set link expiration defaults
- Configure analytics tracking
Link Settings:
- Enable/disable custom aliases
- Set maximum alias length
- Configure default expiration period
- Enable/disable QR code generation
- Set link preview options
User Management:
- Create additional administrator accounts if needed
- Configure user registration settings
- Set email verification requirements
- Configure user roles and permissions
API Configuration:
- Enable API access for developers
- Generate API keys for integrations
- Set API rate limits
- Configure API documentation access
Create Administrator Account
- Access the admin panel at
/admin - Use the credentials configured in environment variables
- Change the default password immediately
- Enable two-factor authentication for security
- Configure additional admin users as needed
Set Up Link Creation Policies
To control link creation:
- In admin panel, navigate to Settings → Links
- Configure custom alias allowance
- Set expiration date defaults and limits
- Enable/disable QR code generation
- Configure link preview settings
URL Shortening Best Practices
Managing Short Links
- Regularly review and remove expired links
- Monitor link creation patterns for abuse
- Implement link validity checks
- Archive analytics data periodically
- Set up automated cleanup policies
Security Considerations
- Enable password protection for sensitive links
- Use custom aliases carefully to prevent conflicts
- Monitor for phishing or malicious content
- Implement link scanning with external services
- Review access logs for suspicious activity
Performance Optimization
- Use caching for frequently accessed redirects
- Monitor database query performance
- Optimize analytics queries
- Enable Redis caching for redirect lookups
- Configure CDN for faster redirects (optional)
Analytics and Monitoring
- Track link click statistics regularly
- Monitor referrer sources and devices
- Set up alerts for unusual activity
- Review user behavior patterns
- Generate reports on popular links
Deployment Best Practices
Security Measures
- Keep Chhoto URL updated to the latest version
- Use strong, unique passwords for all accounts
- Enable two-factor authentication for administrators
- Configure firewall rules to restrict access if needed
- Use HTTPS for all communications (automatic with Klutch.sh)
- Regularly review user access permissions
- Implement rate limiting on link creation
Monitoring and Maintenance
- Monitor disk usage for data and logs
- Set up alerts for deployment failures
- Review logs regularly for errors or security issues
- Schedule maintenance windows for updates
- Test backup restoration procedures monthly
- Monitor database performance
Scaling Considerations
As your URL shortening service grows:
- Increase volume sizes proactively before running out of space
- Monitor database performance and optimize queries
- Implement link analytics archiving
- Consider read replicas for analytics queries
- Archive old link data for compliance
Accessing Chhoto URL
Once deployment is complete and configured:
- Users access Chhoto URL at your configured domain or
example-app.klutch.sh - Users can create short links from long URLs
- Users can customize aliases for branded links
- Users can generate QR codes for short links
- Users can view click analytics for their links
- Admin panel provides full service management
Troubleshooting Deployment Issues
Application Won’t Start
Check the following:
- Verify all required environment variables are set
- Ensure database connection string is correct
- Check that Redis is accessible
- Review application logs in the dashboard
- Verify Node.js version compatibility
Database Connection Errors
Steps to resolve:
- Verify DATABASE_URL environment variable format
- Ensure database is running and accessible
- Check database user credentials
- Verify network connectivity between services
- Test database connectivity from application logs
Short Link Generation Issues
Possible solutions:
- Verify application has write permissions to data directory
- Check available disk space on volumes
- Ensure database is not at capacity
- Verify BASE_URL is correctly configured
- Review link creation logs for errors
Performance Issues
Optimization steps:
- Increase application memory allocation
- Enable Redis caching for redirects
- Optimize database queries
- Configure query result caching
- Monitor and archive old analytics data
Advanced Configuration
Environment Variables for Customization
You can customize Chhoto URL behavior with these environment variables:
# Link ConfigurationSHORT_LINK_PREFIX=sALLOW_CUSTOM_ALIASES=trueMAX_ALIAS_LENGTH=30DEFAULT_EXPIRATION_DAYS=365
# Database Connection PoolDB_POOL_MIN=2DB_POOL_MAX=10DB_IDLE_TIMEOUT=30000
# AnalyticsTRACK_IP_ADDRESS=falseTRACK_USER_AGENT=trueENABLE_GEOGRAPHIC_TRACKING=false
# Feature FlagsENABLE_QR_CODES=trueENABLE_LINK_PREVIEW=trueENABLE_API_KEYS=trueENABLE_BULK_SHORTENING=false
# Cache ConfigurationCACHE_TTL=3600REDIS_MAX_RETRIES=3
# SecurityENFORCE_HTTPS=trueSECURE_COOKIES=trueRATE_LIMIT_WINDOW=900000RATE_LIMIT_MAX_REQUESTS=100Custom Domain Setup
To use a custom domain with your Chhoto URL instance:
- In your Klutch.sh dashboard, navigate to Domains
- Add your custom domain
- Follow the DNS configuration instructions
- Update your environment variables with the new domain:
BASE_URL=https://your-domain.com
- Save and redeploy your application
API Integration
To enable API access for programmatic link creation:
- In Chhoto URL admin panel, navigate to API Settings
- Generate API keys for your applications
- Configure API rate limits
- Document API endpoints for developers
- Set up API usage monitoring
Additional Resources
Learn more about Chhoto URL and Klutch.sh:
- Chhoto URL GitHub Repository - Source code and contribution guidelines
- Chhoto URL Documentation - Comprehensive platform documentation
- Chhoto URL Issue Tracker - Report bugs and request features
- Klutch.sh Official Website - Learn more about the deployment platform
- Klutch.sh Documentation - Platform guides and API reference
Conclusion
You now have a fully functional Chhoto URL instance running on Klutch.sh! Your self-hosted URL shortening service is ready for users to create and manage short links.
With the robust infrastructure provided by Klutch.sh and the powerful features of Chhoto URL, you can create a branded URL shortening solution with complete control. Remember to:
- Keep your application updated with the latest Chhoto URL releases
- Monitor link creation and usage patterns
- Maintain regular backups of your database
- Follow security best practices for link handling
- Scale your infrastructure as your link volume grows
For additional support or questions about deploying Chhoto URL on Klutch.sh, refer to the documentation and community resources linked above.