Skip to content

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
└── .dockerignore

Creating the Dockerfile

Create a Dockerfile for your dpaste deployment:

FROM python:3.11-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Install system dependencies
RUN apt-get update && apt-get install -y \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy project files
COPY . .
# Create necessary directories
RUN mkdir -p /app/staticfiles
# Collect static files
RUN python manage.py collectstatic --noinput
# Expose port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" || exit 1
# Start gunicorn
CMD ["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.0
dpaste>=3.7
gunicorn>=21.0
psycopg2-binary>=2.9
whitenoise>=6.0
python-dotenv>=1.0

Creating Django Settings

Create dpaste_project/settings.py:

import os
from pathlib import Path
from 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'
# Database
database_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',
}
}
# Internationalization
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# dpaste settings
DPASTE_SLUG_LENGTH = 8
DPASTE_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 bytes
DPASTE_MAX_CONTENT_LENGTH = int(os.environ.get('DPASTE_MAX_SIZE', 250000)) # 250KB
# Custom branding
DPASTE_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 os
from 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 python
import os
import 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
*.md
LICENSE
.gitignore
.DS_Store
__pycache__/
*.pyc
.env
*.sqlite3

Deploying dpaste on Klutch.sh

Follow these steps to deploy your dpaste instance:

    Generate a Secret Key

    Generate a secure Django secret key:

    Terminal window
    python -c "import secrets; print(secrets.token_urlsafe(50))"

    Push Your Repository to GitHub

    Initialize and push your configuration:

    Terminal window
    git init
    git add .
    git commit -m "Initial dpaste configuration"
    git remote add origin https://github.com/yourusername/dpaste-deploy.git
    git push -u origin main

    Create 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:

    • Select HTTP as the traffic type
    • Set the internal port to 8000

    Set Environment Variables

    Configure the following environment variables:

    VariableValue
    SECRET_KEYYour generated secret key
    ALLOWED_HOSTSyour-app.klutch.sh
    DEBUGFalse
    DPASTE_SITE_NAMEYour Pastebin

    Attach Persistent Volumes

    For SQLite deployments, attach a volume:

    Mount PathRecommended SizePurpose
    /app1 GBDatabase 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:

  1. Navigate to your dpaste URL
  2. Paste or type your content in the text area
  3. Select the syntax highlighting language (or auto-detect)
  4. Choose an expiration time
  5. 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 view
https://your-dpaste.klutch.sh/abc123xy/
# Raw text
https://your-dpaste.klutch.sh/abc123xy/raw/

API Usage

Creating Pastes via API

Use the API to create pastes programmatically:

Terminal window
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

ParameterDescriptionDefault
contentThe paste contentRequired
lexerSyntax highlighting languagetext
expiresExpiration in seconds604800 (1 week)
filenameOptional filename for lexer detection-

Command-Line Integration

Create a shell alias for easy pasting:

Terminal window
# Add to ~/.bashrc or ~/.zshrc
dpaste() {
curl -s -X POST https://your-dpaste.klutch.sh/api/ \
-d "content=$(cat -)" \
-d "lexer=${1:-text}"
}
# Usage
cat script.py | dpaste python
echo "Quick note" | dpaste

Git Integration

Create a Git alias for pasting diffs:

Terminal window
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'
# Usage
git paste

Customization

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_lexers
for 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 IP
DPASTE_RATE_LIMIT = '10/m'
# 100 pastes per hour per IP
DPASTE_RATE_LIMIT = '100/h'

Content Size Limits

Set maximum paste size:

# 250KB default
DPASTE_MAX_CONTENT_LENGTH = 250000
# 1MB
DPASTE_MAX_CONTENT_LENGTH = 1000000

Production 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:

Terminal window
python manage.py cleanup_snippets

Set 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:

  1. Copy the database file regularly
  2. Store backups securely

For PostgreSQL:

  1. Regular database dumps
  2. 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

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.