Deploying dpaste
Introduction
dpaste is a simple, self-hosted pastebin application written in Python with Django. It provides a clean, no-frills interface for sharing code snippets and text with automatic syntax highlighting for dozens of programming languages. Unlike public pastebin services, self-hosting dpaste gives you complete control over your data and privacy.
The application focuses on doing one thing well: storing and displaying text snippets with optional syntax highlighting. There’s no user registration required, no social features, just a straightforward tool for sharing code and text. This simplicity makes it ideal for development teams, educational environments, or anyone who wants a private pastebin service.
Key highlights of dpaste:
- Simple Interface: Clean, distraction-free design focused on code sharing
- Syntax Highlighting: Support for 200+ languages via Pygments
- Automatic Expiration: Snippets expire after a configurable time
- API Access: Simple REST API for programmatic paste creation
- No Registration Required: Share code instantly without creating accounts
- Multiple Formats: Raw text, code with highlighting, or wrapped views
- Line Numbers: Optional line numbering for code review
- URL Shortening: Short, memorable URLs for easy sharing
- Delete Protection: Optional one-time-view snippets
- 100% Open Source: MIT licensed with straightforward Django codebase
This guide walks through deploying dpaste on Klutch.sh, customizing the configuration, and using the API for integration with development tools.
Why Deploy dpaste on Klutch.sh
Deploying dpaste on Klutch.sh provides several advantages for code sharing:
Simplified Deployment: Klutch.sh handles container orchestration for your Django application.
Private Sharing: Keep your code snippets on your own infrastructure rather than public services.
Persistent Storage: Database storage persists across container restarts.
HTTPS by Default: Secure code sharing with automatic SSL certificates.
GitHub Integration: Connect your configuration repository for automated deployments.
Custom Domains: Use your own domain for a professional pastebin URL.
Prerequisites
Before deploying dpaste on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your configuration
- Basic familiarity with Django applications
- (Optional) A custom domain for your pastebin
Understanding dpaste Architecture
dpaste is a standard Django application:
Django Backend: Handles URL routing, paste storage, and template rendering.
Database: Stores paste content, metadata, and expiration information. SQLite works for small deployments; PostgreSQL recommended for production.
Pygments: The Python syntax highlighting library provides code formatting.
Static Files: CSS and JavaScript for the web interface.
Preparing Your Repository
Create a GitHub repository with your dpaste configuration.
Repository Structure
dpaste-deploy/├── Dockerfile├── requirements.txt├── dpaste_project/│ ├── __init__.py│ ├── settings.py│ ├── urls.py│ └── wsgi.py├── manage.py└── .dockerignoreCreating the Dockerfile
Create a Dockerfile for your dpaste deployment:
FROM python:3.11-slim
# Set environment variablesENV PYTHONDONTWRITEBYTECODE=1ENV PYTHONUNBUFFERED=1
# Install system dependenciesRUN apt-get update && apt-get install -y \ libpq-dev \ gcc \ && rm -rf /var/lib/apt/lists/*
# Set working directoryWORKDIR /app
# Install Python dependenciesCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt
# Copy project filesCOPY . .
# Create necessary directoriesRUN mkdir -p /app/staticfiles
# Collect static filesRUN python manage.py collectstatic --noinput
# Expose portEXPOSE 8000
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" || exit 1
# Start gunicornCMD ["sh", "-c", "python manage.py migrate && gunicorn --bind 0.0.0.0:8000 --workers 2 dpaste_project.wsgi:application"]Creating requirements.txt
Create requirements.txt:
Django>=4.2,<5.0dpaste>=3.7gunicorn>=21.0psycopg2-binary>=2.9whitenoise>=6.0python-dotenv>=1.0Creating Django Settings
Create dpaste_project/settings.py:
import osfrom pathlib import Pathfrom dotenv import load_dotenv
load_dotenv()
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ.get('SECRET_KEY', 'change-this-in-production')DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',')
INSTALLED_APPS = [ 'django.contrib.staticfiles', 'dpaste.apps.dpasteConfig',]
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',]
ROOT_URLCONF = 'dpaste_project.urls'
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', ], }, },]
WSGI_APPLICATION = 'dpaste_project.wsgi.application'
# Databasedatabase_url = os.environ.get('DATABASE_URL')if database_url: import dj_database_url DATABASES = {'default': dj_database_url.parse(database_url)}else: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }
# InternationalizationLANGUAGE_CODE = 'en-us'TIME_ZONE = 'UTC'USE_I18N = TrueUSE_TZ = True
# Static filesSTATIC_URL = '/static/'STATIC_ROOT = BASE_DIR / 'staticfiles'STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# dpaste settingsDPASTE_SLUG_LENGTH = 8DPASTE_SLUG_CHOICES = 'abcdefghijklmnopqrstuvwxyz0123456789'DPASTE_LEXER_DEFAULT = 'python'
# Expiration choices (in seconds)DPASTE_EXPIRE_CHOICES = ( ('onetime', 'One-Time View'), (3600, '1 Hour'), (3600 * 24, '1 Day'), (3600 * 24 * 7, '1 Week'), (3600 * 24 * 30, '1 Month'), ('never', 'Never'),)DPASTE_EXPIRE_DEFAULT = 3600 * 24 * 7 # 1 week
# Rate limiting (pastes per IP per minute)DPASTE_RATE_LIMIT = os.environ.get('DPASTE_RATE_LIMIT', '10/m')
# Maximum paste size in bytesDPASTE_MAX_CONTENT_LENGTH = int(os.environ.get('DPASTE_MAX_SIZE', 250000)) # 250KB
# Custom brandingDPASTE_SITE_NAME = os.environ.get('DPASTE_SITE_NAME', 'dpaste')Creating URL Configuration
Create dpaste_project/urls.py:
from django.urls import path, include
urlpatterns = [ path('', include('dpaste.urls.dpaste')),]Creating WSGI Configuration
Create dpaste_project/wsgi.py:
import osfrom django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dpaste_project.settings')application = get_wsgi_application()Creating manage.py
Create manage.py:
#!/usr/bin/env pythonimport osimport sys
if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dpaste_project.settings') from django.core.management import execute_from_command_line execute_from_command_line(sys.argv)Creating the .dockerignore File
Create a .dockerignore file:
.git.github*.mdLICENSE.gitignore.DS_Store__pycache__/*.pyc.env*.sqlite3Deploying dpaste on Klutch.sh
Follow these steps to deploy your dpaste instance:
- Select HTTP as the traffic type
- Set the internal port to 8000
Generate a Secret Key
Generate a secure Django secret key:
python -c "import secrets; print(secrets.token_urlsafe(50))"Push Your Repository to GitHub
Initialize and push your configuration:
git initgit add .git commit -m "Initial dpaste configuration"git remote add origin https://github.com/yourusername/dpaste-deploy.gitgit push -u origin mainCreate a New Project on Klutch.sh
Navigate to the Klutch.sh dashboard and create a new project for your pastebin.
Create a New App
Create a new app within your project and connect your GitHub repository.
Configure HTTP Traffic
In the deployment settings:
Set Environment Variables
Configure the following environment variables:
| Variable | Value |
|---|---|
SECRET_KEY | Your generated secret key |
ALLOWED_HOSTS | your-app.klutch.sh |
DEBUG | False |
DPASTE_SITE_NAME | Your Pastebin |
Attach Persistent Volumes
For SQLite deployments, attach a volume:
| Mount Path | Recommended Size | Purpose |
|---|---|---|
/app | 1 GB | Database and application data |
For PostgreSQL, configure the database URL instead.
Deploy Your Application
Click Deploy to build and start dpaste.
Access dpaste
Navigate to https://your-app-name.klutch.sh to access your pastebin.
Using dpaste
Creating Pastes
Create a paste through the web interface:
- Navigate to your dpaste URL
- Paste or type your content in the text area
- Select the syntax highlighting language (or auto-detect)
- Choose an expiration time
- Click “Save”
Viewing Pastes
Each paste gets a unique URL like:
https://your-dpaste.klutch.sh/abc123xy/View options:
- Default: Syntax-highlighted view
- Raw: Plain text (
/raw/) - Slim: Minimal styling (
/slim/)
Sharing Code
Share paste URLs directly or use the raw URL for embedding:
# Highlighted viewhttps://your-dpaste.klutch.sh/abc123xy/
# Raw texthttps://your-dpaste.klutch.sh/abc123xy/raw/API Usage
Creating Pastes via API
Use the API to create pastes programmatically:
curl -X POST https://your-dpaste.klutch.sh/api/ \ -d "content=print('Hello, World!')" \ -d "lexer=python" \ -d "expires=86400"Response:
{ "url": "https://your-dpaste.klutch.sh/abc123xy/", "lexer": "python", "content": "print('Hello, World!')"}API Parameters
| Parameter | Description | Default |
|---|---|---|
content | The paste content | Required |
lexer | Syntax highlighting language | text |
expires | Expiration in seconds | 604800 (1 week) |
filename | Optional filename for lexer detection | - |
Command-Line Integration
Create a shell alias for easy pasting:
# Add to ~/.bashrc or ~/.zshrcdpaste() { curl -s -X POST https://your-dpaste.klutch.sh/api/ \ -d "content=$(cat -)" \ -d "lexer=${1:-text}"}
# Usagecat script.py | dpaste pythonecho "Quick note" | dpasteGit Integration
Create a Git alias for pasting diffs:
git config --global alias.paste '!f() { git diff | curl -s -X POST https://your-dpaste.klutch.sh/api/ -d "content=$(cat -)" -d "lexer=diff"; }; f'
# Usagegit pasteCustomization
Supported Languages
dpaste uses Pygments for syntax highlighting, supporting 500+ languages including:
- Python, JavaScript, TypeScript
- Java, C, C++, C#, Go, Rust
- HTML, CSS, SCSS, SASS
- SQL, JSON, YAML, XML
- Bash, PowerShell, Dockerfile
- And many more
View all lexers:
from pygments.lexers import get_all_lexersfor lexer in get_all_lexers(): print(lexer[0])Expiration Settings
Configure expiration options in settings:
DPASTE_EXPIRE_CHOICES = ( ('onetime', 'One-Time View'), (3600, '1 Hour'), (3600 * 24, '1 Day'), (3600 * 24 * 7, '1 Week'), (3600 * 24 * 30, '1 Month'), (3600 * 24 * 365, '1 Year'), ('never', 'Never'),)Rate Limiting
Protect against abuse with rate limiting:
# 10 pastes per minute per IPDPASTE_RATE_LIMIT = '10/m'
# 100 pastes per hour per IPDPASTE_RATE_LIMIT = '100/h'Content Size Limits
Set maximum paste size:
# 250KB defaultDPASTE_MAX_CONTENT_LENGTH = 250000
# 1MBDPASTE_MAX_CONTENT_LENGTH = 1000000Production Best Practices
Database Recommendations
For production deployments:
SQLite: Suitable for low-traffic instances
PostgreSQL: Recommended for higher traffic and reliability
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'dpaste', 'USER': 'dpaste', 'PASSWORD': os.environ.get('DB_PASSWORD'), 'HOST': os.environ.get('DB_HOST'), 'PORT': '5432', }}Cleanup Expired Pastes
Run periodic cleanup of expired pastes:
python manage.py cleanup_snippetsSet up a scheduled job to run this regularly.
Security Recommendations
- Rate Limiting: Prevent spam and abuse
- Content Limits: Restrict paste sizes
- HTTPS Only: Ensure all traffic is encrypted
- No Sensitive Data: Remind users not to paste secrets
Backup Strategy
For SQLite:
- Copy the database file regularly
- Store backups securely
For PostgreSQL:
- Regular database dumps
- Point-in-time recovery setup
Troubleshooting Common Issues
Pastes Not Saving
Symptoms: Paste creation fails or returns errors.
Solutions:
- Check database connectivity
- Verify disk space is available
- Review rate limiting settings
- Check content size limits
Syntax Highlighting Not Working
Symptoms: Code appears without highlighting.
Solutions:
- Verify Pygments is installed
- Check selected lexer is valid
- Try selecting language manually
Static Files Not Loading
Symptoms: CSS/JS not appearing.
Solutions:
- Verify collectstatic ran successfully
- Check WhiteNoise configuration
- Review STATIC_URL setting
Slow Performance
Symptoms: Page loads are slow.
Solutions:
- Increase worker count
- Upgrade to PostgreSQL
- Clean up expired pastes
- Add caching layer
Additional Resources
- dpaste Documentation
- dpaste GitHub Repository
- Pygments Lexer Documentation
- Django Documentation
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Conclusion
Deploying dpaste on Klutch.sh gives you a simple, private pastebin for sharing code and text. The combination of dpaste’s focused feature set and Klutch.sh’s container management means you get a reliable code sharing tool without unnecessary complexity.
With syntax highlighting for hundreds of languages, API access for automation, and flexible expiration options, dpaste handles everyday code sharing needs efficiently. Whether you’re collaborating with teammates, sharing code snippets in chat, or building automated workflows, dpaste on Klutch.sh provides a fast, private alternative to public pastebin services.