Sharing code snippets, configuration files, or sensitive information online shouldn’t mean surrendering your privacy to third-party services. While public pastebin services like Pastebin.com or GitHub Gists are convenient, they come with privacy concerns: your data is stored on someone else’s servers, potentially analyzed, logged, or even sold.

💡 This article contains affiliate links. If you buy through them, we earn a small commission at no extra cost to you. Learn more.

Self-hosting your own pastebin gives you complete control over your data, ensures end-to-end encryption, and provides a reliable way to share text securely with colleagues, friends, or your team. In this comprehensive guide, we’ll compare the two leading self-hosted pastebin solutions in 2026 — PrivateBin and Hemmelig — and walk you through setting up both on Docker.

Why Self-Host a Pastebin?

Before diving into the technical details, let’s explore why you’d want to run your own pastebin service:

Privacy and Data Ownership: When you self-host, your sensitive code snippets, API keys, logs, and configuration files never leave your infrastructure. You control who has access and for how long.

End-to-End Encryption: Both PrivateBin and Hemmelig encrypt content in the browser before it’s sent to the server. This means even you, as the server administrator, cannot read the content without the decryption key.

No Ads or Tracking: Public pastebin services often inject ads, track users, or require registration. Your self-hosted solution is clean, fast, and respects user privacy.

Custom Retention Policies: Define your own expiration rules. Keep pastes for 5 minutes, a day, or forever — it’s your choice.

Team Collaboration: Provide your team or community with a trusted, private platform for sharing snippets without relying on external services.

PrivateBin vs Hemmelig: Feature Comparison

Let’s break down the key differences between these two popular self-hosted pastebin solutions.

PrivateBin

PrivateBin is the most mature and widely-used self-hosted pastebin. It’s a minimalist, zero-knowledge paste service where the server has no knowledge of the pasted data.

Key Features:

  • Zero-knowledge encryption: All data is encrypted/decrypted in the browser using AES-256
  • Burn after reading: Pastes can self-destruct after being read once
  • Syntax highlighting: Supports dozens of programming languages
  • File attachments: Upload and share encrypted files
  • Password protection: Add an extra layer of security with passwords
  • Configurable expiration: 5 minutes to never
  • Discussion threads: Enable comments on pastes (also encrypted)
  • QR code generation: Easy mobile sharing
  • Lightweight: Runs on minimal resources
  • Multiple storage backends: Filesystem, database, S3, Google Cloud Storage

Technology Stack:

  • Written in PHP
  • No database required (filesystem backend by default)
  • Works with SQLite, MySQL, PostgreSQL for larger deployments
  • Simple, battle-tested codebase

Best For:

  • Users who prioritize stability and maturity
  • Minimal resource consumption
  • Simple deployment with no database requirements
  • Organizations needing proven, audited encryption

Hemmelig

Hemmelig (Norwegian for “secret”) is a newer, modern take on the pastebin concept with a sleek UI and some unique features.

Key Features:

  • End-to-end encryption: AES-256-GCM encryption in the browser
  • Modern, intuitive UI: Clean, responsive design with dark mode
  • User accounts: Optional registration for managing pastes
  • Burn after reading: One-time view option
  • Password protection: Additional security layer
  • Configurable expiration: Flexible retention policies
  • File uploads: Share encrypted files alongside text
  • QR codes: Mobile-friendly sharing
  • Admin dashboard: Manage users and monitor usage
  • Markdown support: Rich text rendering
  • Public/private pastes: Choose visibility per paste

Technology Stack:

  • Built with Node.js and React
  • Requires PostgreSQL database
  • Modern JavaScript ecosystem
  • Active development with frequent updates

Best For:

  • Teams needing user account management
  • Users who prefer modern, polished interfaces
  • Organizations wanting granular admin controls
  • Projects already running Node.js infrastructure

Performance and Resource Usage

PrivateBin is incredibly lightweight. A typical Docker deployment uses:

  • RAM: ~50-100 MB
  • CPU: Minimal (mostly idle)
  • Storage: Only the pastes themselves (configurable limits)
  • Database: Optional (can run filesystem-only)

Hemmelig requires more resources due to its modern stack:

  • RAM: ~150-300 MB (Node.js + PostgreSQL)
  • CPU: Low to moderate
  • Storage: Pastes + PostgreSQL database
  • Database: PostgreSQL required

For small homelabs or resource-constrained environments, PrivateBin has the clear advantage. If you’re already running PostgreSQL and Node.js services, Hemmelig integrates seamlessly.

Security and Encryption

Both solutions implement zero-knowledge encryption, meaning:

  1. Content is encrypted in the user’s browser before transmission
  2. The server stores only encrypted data
  3. The decryption key is in the URL fragment (never sent to the server)
  4. Even the server administrator cannot read paste content

PrivateBin has undergone multiple security audits and has a longer track record. Its encryption implementation is well-documented and peer-reviewed.

Hemmelig uses modern cryptographic standards (AES-256-GCM) and follows best practices, but being newer, it has less battle-testing in production environments.

Verdict: Both are secure for most use cases. PrivateBin gets the edge for organizations requiring audited, proven encryption.

How to Set Up PrivateBin on Docker

Let’s deploy PrivateBin using Docker Compose. This setup uses the filesystem backend (no database required).

Prerequisites

  • Docker and Docker Compose installed
  • A domain or subdomain (e.g., paste.yourdomain.com)
  • A reverse proxy (we’ll use Traefik in this example)

Docker Compose Configuration

Create a directory for PrivateBin:

1
2
mkdir -p ~/homelab/privatebin
cd ~/homelab/privatebin

Create a docker-compose.yml file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3.8'

services:
  privatebin:
    image: privatebin/nginx-fpm-alpine:latest
    container_name: privatebin
    restart: unless-stopped
    read_only: true
    volumes:
      - ./data:/srv/data
      - ./config/conf.php:/srv/cfg/conf.php:ro
    tmpfs:
      - /tmp
      - /run
    environment:
      - TZ=Europe/Berlin
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.privatebin.rule=Host(`paste.yourdomain.com`)"
      - "traefik.http.routers.privatebin.entrypoints=websecure"
      - "traefik.http.routers.privatebin.tls.certresolver=letsencrypt"
      - "traefik.http.services.privatebin.loadbalancer.server.port=8080"
    networks:
      - traefik

networks:
  traefik:
    external: true

Create Configuration File

PrivateBin uses a PHP configuration file. Create config/conf.php:

1
mkdir -p config

Create config/conf.php:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
$CONFIG = [
    'main' => [
        'name' => 'PrivateBin',
        'discussion' => true,
        'opendiscussion' => false,
        'password' => true,
        'fileupload' => true,
        'burnafterreadingselected' => false,
        'defaultformatter' => 'plaintext',
        'syntaxhighlightingtheme' => 'sons-of-obsidian',
        'sizelimit' => 10485760, // 10 MB
        'template' => 'bootstrap',
        'languageselection' => false,
        'languagedefault' => 'en',
        'qrcode' => true,
    ],
    'expire' => [
        'default' => '1week',
    ],
    'expire_options' => [
        '5min' => 300,
        '10min' => 600,
        '1hour' => 3600,
        '1day' => 86400,
        '1week' => 604800,
        '1month' => 2592000,
        '1year' => 31536000,
        'never' => 0,
    ],
    'traffic' => [
        'limit' => 10,
        'exempted' => '',
    ],
    'model' => [
        'class' => 'Filesystem',
    ],
    'model_options' => [
        'dir' => '/srv/data',
    ],
];

Deploy PrivateBin

1
2
3
4
5
6
7
8
9
# Create data directory
mkdir -p data
chmod 777 data  # PrivateBin runs as nginx user

# Start the container
docker-compose up -d

# Check logs
docker-compose logs -f

Access PrivateBin at https://paste.yourdomain.com. That’s it! You now have a secure, self-hosted pastebin running.

Optional: Database Backend

For higher traffic or better performance, you can use a database. Here’s how to switch to PostgreSQL:

Update docker-compose.yml to add PostgreSQL:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '3.8'

services:
  privatebin:
    image: privatebin/nginx-fpm-alpine:latest
    container_name: privatebin
    restart: unless-stopped
    depends_on:
      - db
    volumes:
      - ./config/conf.php:/srv/cfg/conf.php:ro
    # ... (rest of configuration)

  db:
    image: postgres:16-alpine
    container_name: privatebin_db
    restart: unless-stopped
    environment:
      POSTGRES_DB: privatebin
      POSTGRES_USER: privatebin
      POSTGRES_PASSWORD: your_secure_password
    volumes:
      - ./db_data:/var/lib/postgresql/data
    networks:
      - traefik

Update config/conf.php:

1
2
3
4
5
6
7
8
9
'model' => [
    'class' => 'Database',
],
'model_options' => [
    'dsn' => 'pgsql:host=db;dbname=privatebin',
    'usr' => 'privatebin',
    'pwd' => 'your_secure_password',
    'opt' => [PDO::ATTR_PERSISTENT => true],
],

How to Set Up Hemmelig on Docker

Hemmelig requires PostgreSQL, so our setup will include both services.

Docker Compose Configuration

Create a directory for Hemmelig:

1
2
mkdir -p ~/homelab/hemmelig
cd ~/homelab/hemmelig

Create docker-compose.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
version: '3.8'

services:
  hemmelig:
    image: hemmeligapp/hemmelig:latest
    container_name: hemmelig
    restart: unless-stopped
    depends_on:
      - postgres
    environment:
      - DATABASE_URL=postgresql://hemmelig:your_secure_password@postgres:5432/hemmelig
      - JWT_SECRET=your_very_long_random_secret_key_here
      - HOST=0.0.0.0
      - PORT=3000
      - RATE_LIMIT=100
      - DISABLE_USERS=false  # Set to true to disable user registration
      - DISABLE_FILE_UPLOAD=false
      - MAX_FILE_SIZE=10485760  # 10 MB
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hemmelig.rule=Host(`secret.yourdomain.com`)"
      - "traefik.http.routers.hemmelig.entrypoints=websecure"
      - "traefik.http.routers.hemmelig.tls.certresolver=letsencrypt"
      - "traefik.http.services.hemmelig.loadbalancer.server.port=3000"
    networks:
      - traefik

  postgres:
    image: postgres:16-alpine
    container_name: hemmelig_db
    restart: unless-stopped
    environment:
      POSTGRES_DB: hemmelig
      POSTGRES_USER: hemmelig
      POSTGRES_PASSWORD: your_secure_password
    volumes:
      - ./db_data:/var/lib/postgresql/data
    networks:
      - traefik

networks:
  traefik:
    external: true

Generate JWT Secret

Generate a secure JWT secret:

1
openssl rand -base64 32

Replace your_very_long_random_secret_key_here in the docker-compose.yml with the generated value.

Deploy Hemmelig

1
2
3
4
5
# Start the containers
docker-compose up -d

# Check logs
docker-compose logs -f hemmelig

Access Hemmelig at https://secret.yourdomain.com. The first time you visit, you can create an admin account.

Configuration Options

Hemmelig offers several environment variables for customization:

  • DISABLE_USERS: Set to true to disable user registration (anonymous-only mode)
  • DISABLE_FILE_UPLOAD: Set to true to block file attachments
  • MAX_FILE_SIZE: Maximum upload size in bytes
  • RATE_LIMIT: Requests per minute per IP
  • ADMIN_EMAIL: Email for the default admin account

Which One Should You Choose?

Here’s a decision matrix to help you choose:

Choose PrivateBin if you:

  • Want the lightest possible resource footprint
  • Prefer proven, battle-tested software
  • Don’t need user account management
  • Want to run without a database
  • Value simplicity and stability over modern UI

Choose Hemmelig if you:

  • Need user accounts and team management
  • Prefer modern, polished interfaces
  • Already run PostgreSQL infrastructure
  • Want an admin dashboard for monitoring
  • Value active development and new features

Both are excellent choices, and you can’t go wrong with either. For most homelab users, PrivateBin is the safer, simpler bet. For teams or organizations, Hemmelig offers more management features.

Security Best Practices

Regardless of which solution you choose, follow these security best practices:

1. Use HTTPS Always

Never run a pastebin over plain HTTP. Encryption happens in the browser, but HTTP can still expose metadata and enable man-in-the-middle attacks.

Use Traefik, Caddy, or nginx with Let’s Encrypt certificates.

2. Set Appropriate Expiration Defaults

Configure sensible default expiration times. For most use cases, 1 week or 1 month is reasonable. Avoid “never” as a default to prevent indefinite storage of potentially sensitive data.

3. Limit File Upload Sizes

Both solutions allow file uploads. Limit the maximum size to prevent abuse and storage exhaustion:

  • PrivateBin: Set sizelimit in conf.php
  • Hemmelig: Set MAX_FILE_SIZE environment variable

Recommended limits: 5-10 MB for most use cases.

4. Implement Rate Limiting

Protect against abuse with rate limiting:

  • PrivateBin: Built-in traffic limiting in conf.php
  • Hemmelig: RATE_LIMIT environment variable
  • Additional: Use your reverse proxy (Traefik, nginx) for IP-based rate limiting

5. Regular Backups

Back up your pastebin data regularly:

PrivateBin (filesystem):

1
2
# Backup data directory
tar -czf privatebin-backup-$(date +%F).tar.gz data/

Hemmelig (PostgreSQL):

1
2
# Database backup
docker exec hemmelig_db pg_dump -U hemmelig hemmelig > hemmelig-backup-$(date +%F).sql

Automate backups with cron or use solutions like Duplicati, Restic, or Borg for comprehensive backup strategies.

6. Monitor and Prune Old Pastes

Implement cleanup policies to remove expired pastes:

PrivateBin: Automatic purge based on expiration settings (no manual action needed)

Hemmelig: Built-in expiration handling

7. Disable Registration (If Not Needed)

If you’re running a personal pastebin or internal team tool, disable public registration:

  • PrivateBin: No user accounts by design
  • Hemmelig: Set DISABLE_USERS=true

Integration and API Usage

Both solutions can be integrated into your workflows.

PrivateBin API

PrivateBin doesn’t have an official REST API, but the community has created CLI tools:

pbincli (Python):

1
2
3
4
5
6
7
pip install pbincli

# Create a paste
pbincli send -t "My code snippet" -f myfile.py

# Retrieve a paste
pbincli get https://paste.yourdomain.com/?paste-id

Hemmelig API

Hemmelig has a built-in REST API. Example using curl:

Create a secret:

1
2
3
4
5
6
7
curl -X POST https://secret.yourdomain.com/api/v1/secret \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My secret text",
    "password": "optional_password",
    "ttl": 3600
  }'

Retrieve a secret:

1
curl https://secret.yourdomain.com/api/v1/secret/{secret_id}

Check Hemmelig’s documentation for the full API specification.

Maintenance and Updates

PrivateBin Updates

1
2
3
cd ~/homelab/privatebin
docker-compose pull
docker-compose up -d

PrivateBin is very stable and rarely requires manual intervention. Updates are typically security patches or minor feature additions.

Hemmelig Updates

1
2
3
cd ~/homelab/hemmelig
docker-compose pull
docker-compose up -d

Hemmelig is more actively developed, so check the changelog before updating.

Automating Updates

Use Watchtower to automate Docker container updates:

1
2
3
4
5
6
docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower \
  --cleanup \
  --interval 86400

Troubleshooting Common Issues

PrivateBin: “Error: Paste does not exist”

Cause: The data directory isn’t writable or pastes expired.

Fix:

1
chmod 777 ~/homelab/privatebin/data

Hemmelig: Database Connection Failed

Cause: PostgreSQL isn’t ready when Hemmelig starts.

Fix: Add a health check to docker-compose.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
postgres:
  # ... other config
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U hemmelig"]
    interval: 5s
    timeout: 5s
    retries: 5

hemmelig:
  depends_on:
    postgres:
      condition: service_healthy

Both: CORS Errors

Cause: Reverse proxy misconfiguration.

Fix: Ensure your reverse proxy passes the correct headers:

Traefik: Add middleware for CORS if needed.

nginx:

1
2
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";

Hardware Recommendations

Both solutions run on minimal hardware. Here’s what you need:

Minimum:

  • CPU: 1 core (any modern CPU)
  • RAM: 512 MB (PrivateBin), 1 GB (Hemmelig)
  • Storage: 5 GB (for the application + pastes)

Recommended:

  • CPU: 2 cores
  • RAM: 2 GB
  • Storage: 20 GB SSD

Any modern mini PC or Raspberry Pi 4 will handle either solution effortlessly. If you’re building a full homelab, check out our guide on the best mini PCs for your homelab in 2026.

Final Thoughts

Self-hosting a pastebin is one of the simplest yet most useful additions to your homelab. Whether you choose PrivateBin for its battle-tested reliability and minimal footprint, or Hemmelig for its modern interface and team features, you’ll gain a private, secure way to share sensitive information.

Both solutions respect user privacy through zero-knowledge encryption, give you full control over your data, and cost nothing beyond your existing infrastructure.

Start with PrivateBin if you’re new to self-hosting or want something lightweight. Experiment with Hemmelig if you need user management or prefer modern UIs. Either way, you’re taking back control of your data — and that’s what self-hosting is all about.

Next Steps:

Have questions about self-hosting pastebin solutions? Drop a comment below or reach out on our community forum. Happy self-hosting!