pasto v0.10.0
Pasto
A Crystal-based pastebin application with live syntax highlighting, SSH access, user accounts, and extensive theme support.
Features
Core Features
- 🚀 Fast & Lightweight: Built with Crystal for excellent performance
- 🎨 Live Preview: Real-time syntax highlighting as you type
- 🌈 Extensive Theming: 321+ syntax highlighting themes from Tartrazine
- 🎭 Smart Language Detection: Auto-detects language with Hansa classification
- 📱 Responsive Design: Works beautifully on desktop and mobile
- 🔒 Built-in Security: Rate limiting and size validation
SSH Access
- 🔑 SSH Paste Creation: Create pastes directly via SSH (
cat file | ssh pasto.example.com) - 👤 SSH Key Authentication: Your SSH key becomes your identity
- 🔗 Automatic Account Linking: SSH keys automatically linked to user accounts
User Accounts & Profiles
- 📋 User Profiles: View and manage all your pastes in one place
- ✏️ Editable Display Names: Personalize your profile
- 🎨 Theme Preferences: UI and syntax theme preferences saved per user
- 🔐 Session Management: Secure web sessions with cookie-based auth
Paste Management
- 📝 Paste Titles: Add optional titles or auto-generate from content
- 📜 Version History: Full edit history with Sepia versioning
- 🕐 View Past Versions: Browse and compare previous versions
- ✏️ Edit Your Pastes: Modify pastes you own
- 🗑️ Delete Pastes: Remove pastes from your profile
Modern UI
- 🎯 Clean Interface: Modern design with Pico CSS and Lucide icons
- 📐 Collapsible Sidebar: Theme controls in a space-saving sidebar
- ⌨️ CodeJar Editor: Lightweight code editor with syntax highlighting
- 🔄 Live Preview Pane: See rendered output as you type
AI Assistant Integration (MCP)
- 🤖 Model Context Protocol: Native MCP support for AI assistant integration
- 🔧 Zero Installation: AI assistants can access pastes without local setup
- 🛡️ Secure Access: Uses existing API keys and authentication
- 📝 Full CRUD: Create, retrieve, list, update, and delete pastes via MCP
- 🎯 Tool Discovery: AI assistants automatically discover available paste operations
Quick Start
Docker (Recommended)
The easiest way to run Pasto is with Docker Compose:
# Clone the repository
git clone https://github.com/ralsina/pasto.git
cd pasto
# Start Pasto (web + SSH server)
docker compose up -d
# View logs
docker compose logs -f
# Stop Pasto
docker compose down
The services will be available at:
- Web interface: http://localhost:3000
- SSH access:
ssh -p 2222 localhost - CLI tool:
pasto-cli --server=localhost login(see CLI.md)
Docker Configuration
The docker-compose.yml file includes:
- pasto service: Web interface on port 3000
- pasto-ssh service: SSH server on port 2222
- Persistent volumes for data, sessions, cache, and SSH keys
To customize, edit the environment variables in docker-compose.yml:
environment:
PASTO_PORT: 3000
PASTO_MAX_PASTE_SIZE: 1048576 # 1MB
PASTO_THEME: monokai
PASTO_RATE_LIMIT: 10
PASTO_SESSION_SECRET: "your-secret-here" # Change in production!
Volumes
| Volume | Path | Description |
|---|---|---|
pasto-data |
/app/data |
Pastes, users, SSH keys (back this up!) |
pasto-sessions |
/app/sessions |
Web sessions |
pasto-cache |
/app/public/cache |
Rendered HTML cache |
pasto-ssh-keys |
/app/ssh-keys |
SSH host keys |
Backup
# Backup all data
docker compose exec pasto tar -czf - /app/data > pasto-backup.tar.gz
# Or copy volumes
docker run --rm -v pasto-data:/data -v $(pwd):/backup alpine \
tar -czf /backup/pasto-data-backup.tar.gz /data
Manual Installation
# Clone the repository
git clone https://github.com/ralsina/pasto.git
cd pasto
# Install dependencies
shards install
# Build the application
shards build --release
# Run the server
./bin/pasto
SSH Usage
Create a paste via SSH:
# Simplest form - just pipe content
cat myfile.py | ssh -p 2222 pasto.example.com
# Or use echo
echo "Hello, World!" | ssh -p 2222 pasto.example.com
# Redirect from file
ssh -p 2222 pasto.example.com < myfile.py
# Explicit paste command (also works)
cat myfile.py | ssh -p 2222 pasto.example.com paste
The server returns the URL of your new paste.
Other SSH commands:
# Login to link SSH key with web account
ssh -p 2222 pasto.example.com login
# Show help
ssh -p 2222 pasto.example.com help
CLI Usage
The pasto-cli tool provides a convenient command-line interface for Pasto:
# Login to a Pasto server (SSH authentication)
pasto-cli --server=pasto.example.com --ssh-port=2222 login
# Create a paste
echo 'print("Hello, World!")' | pasto-cli paste --language=python
# List your pastes
pasto-cli list
# Get a paste
pasto-cli get <paste-id>
# Delete a paste
pasto-cli delete <paste-id>
The CLI supports:
- SSH-based authentication using your SSH keys
- Automatic host derivation - specify
--serveror--ssh-host, the other is auto-detected - Terminal hyperlinks - clickable paste IDs in supported terminals
- Human-readable timestamps - relative time display
- Full CRUD operations - create, read, update, delete pastes
- Credential storage - saves API keys securely in
~/.config/pasto/credentials.yml
For detailed CLI documentation, see CLI.md.
Zero-Knowledge Encryption
Pasto supports zero-knowledge encryption where you encrypt content locally before sending it to the server. The server never sees your password or can decrypt your content.
Using pasto-crypto CLI Tool
The pasto-crypto tool enables you to encrypt content locally using AES-256-GCM encryption with PBKDF2 key derivation.
Encrypt content locally:
# Encrypt with a random password (recommended for maximum security)
./bin/pasto-crypto encrypt --random-pass --output encrypted.txt input.txt
# Output: Environment variables needed for decryption
# PASTO_PASSWORD=wxyeniX58PDup7O!VR2UGyQejOib%pk!
# PASTO_SALT=SEp4IYOd36ICRA4szDdy2w==
# PASTO_IV=wCKCNS9IW3r/48Md
# PASTO_ITERATIONS=100000
Create encrypted paste via SSH:
# Save the environment variables from encryption
export PASTO_PASSWORD="wxyeniX58PDup7O!VR2UGyQejOib%pk!"
export PASTO_SALT="SEp4IYOd36ICRA4szDdy2w=="
export PASTO_IV="wCKCNS9IW3r/48Md"
# Create paste with zero-knowledge encryption
cat encrypted.txt | ssh -p 2222 pasto.example.com paste \
--iv "$PASTO_IV" \
--salt "$PASTO_SALT" \
--iterations 100000
Decrypt in the browser:
- Open the paste URL in your browser
- Enter the password (not the key!) when prompted
- The content is decrypted client-side using Web Crypto API
What makes it zero-knowledge?
- Password stays with you: The server only stores the salt and IV, never the password
- PBKDF2 key derivation: Your password is securely stretched with 100,000 iterations
- AES-256-GCM encryption: Military-grade encryption
- Client-side decryption: Content is decrypted in your browser, not on the server
- Server can't read: Even if the server is compromised, your encrypted pastes remain secure
Full example workflow:
# 1. Create a file with sensitive content
cat > secret.txt <<EOF
API_KEY=sk_live_1234567890abcdef
DATABASE_URL=postgres://user:pass@localhost/db
EOF
# 2. Encrypt it locally with a random password
./bin/pasto-crypto encrypt --random-pass --output secret.enc secret.txt
# 3. Save the credentials (keep these safe!)
export PASTO_PASSWORD="iJOK#rPpD!GfRwBA5kQZT@0RA5YV7GCG"
export PASTO_SALT="utJ7JzIALDE9Ak1WzCGOnQ=="
export PASTO_IV="AwnXIR7s2313cdBr"
# 4. Create the paste via SSH
cat secret.enc | ssh -p 2222 pasto.example.com paste \
--iv "$PASTO_IV" \
--salt "$PASTO_SALT" \
--title "Production Credentials"
# Output: http://pasto.example.com/abc123-def456
# 🔐 Zero-trust encrypted paste created
# 5. Share the URL + PASSWORD with your teammate
# Teammate opens URL, enters password, and sees decrypted content
# The server administrators cannot see the content even if they wanted to!
Decrypting locally (optional):
# Decrypt the encrypted file back to plaintext
./bin/pasto-crypto decrypt \
--password "$PASTO_PASSWORD" \
--salt "$PASTO_SALT" \
--iv "$PASTO_IV" \
--output decrypted.txt \
encrypted.txt
Security best practices:
- Use
--random-passfor generating strong passwords - Save the password securely (password manager, not in plain text files)
- Share the password through a different channel than the paste URL
- The server stores
encryption_ivandencryption_saltbut cannot decrypt without your password
Web Usage
- Navigate to
http://localhost:3000 - Type or paste your code in the editor
- Watch the live preview update
- Click + to create the paste
Configuration
Pasto supports three configuration methods (in order of priority):
- Command line arguments
- Environment variables (prefixed with
PASTO_) - Configuration file (
pasto.yml)
Command Line Options
./bin/pasto \
--port 3000 \
--bind 0.0.0.0 \
--max-paste-size 102400 \
--theme default-dark \
--ssh-enabled true \
--ssh-port 2222 \
--storage-dir ./data \
--cache-dir ./public/cache
Environment Variables
export PASTO_PORT=3000
export PASTO_MAX_PASTE_SIZE=102400
export PASTO_THEME=monokai
export PASTO_SSH_ENABLED=true
export PASTO_SSH_PORT=2222
export PASTO_RATE_LIMIT=10
Configuration File (pasto.yml)
port: 3000
bind: "0.0.0.0"
max_paste_size: 102400 # 100KB
theme: default-dark
ssh_enabled: true
ssh_port: 2222
storage_dir: ./data
cache_dir: ./public/cache
rate_limit: 10
rate_window: 60
API Endpoints
Create Paste (Web)
curl -X POST http://localhost:3000 \
-d "content=print('Hello!')&language=python&title=My%20Paste"
View Paste
# View paste
curl http://localhost:3000/{paste-id}
# View with language override
curl http://localhost:3000/{paste-id}?lang=python
# View with file extension
curl http://localhost:3000/{paste-id}.py
View Paste History
# View all versions (owner only)
curl http://localhost:3000/{paste-id}/history
# View specific version
curl http://localhost:3000/{paste-id}/version/1
Live Highlighting API
curl -X POST http://localhost:3000/highlight \
-d "content=def hello(): pass&language=python&theme=monokai"
AI Assistant Integration (MCP)
Pasto supports the Model Context Protocol (MCP), enabling AI assistants like Claude to directly interact with your pastes. This allows AI assistants to create, retrieve, and manage pastes without any local setup.
Getting Started
- Generate an API Key: Visit
/profileon your Pasto instance and click "Generate API Key" - Copy the API Key: It will start with
pasto_ak_ - Configure Your AI Assistant: Use the MCP client configuration below
MCP Tools Available
Pasto provides these MCP tools for AI assistants:
create_paste
Create a new paste with content and optional metadata.
Parameters:
content(required): The paste contenttitle(optional): Paste titlelanguage(optional): Programming language for syntax highlightingfilename(optional): Filename for language detectionprivate(optional): Make paste private (default: false)encrypted(optional): Encrypt paste content (default: false)burn_after_reading(optional): Delete after first view (default: false)expires_in(optional): Expiration time - "1h", "1d", "1w", "1m", "never"
Example:
Please create a paste with this Python code: print("Hello, World!")
Make it private and set it to expire in 1 week.
get_paste
Retrieve paste content and metadata by ID.
Parameters:
id(required): The paste ID to retrieve
Example:
Please retrieve the paste with ID abc123 and show me its details.
list_pastes
List user's pastes with pagination and filtering.
Parameters:
page(optional): Page number (default: 1)limit(optional): Items per page, max 100 (default: 20)private_only(optional): Filter to private pastes onlypublic_only(optional): Filter to public pastes onlyencrypted_only(optional): Filter to encrypted pastes onlylanguage(optional): Filter by programming language
Example:
Show me my private Python pastes, 10 at a time.
update_paste
Update an existing paste's content or metadata (creates new version).
Parameters:
id(required): The paste ID to updatecontent(required): New content for the pastetitle(optional): New titlelanguage(optional): New programming languagefilename(optional): New filenameprivate(optional): Make paste privateburn_after_reading(optional): Set burn-after-reading flagexpires_in(optional): Update expiration time
Example:
Update paste xyz789 with this new JavaScript code and make it public.
delete_paste
Permanently delete a paste.
Parameters:
id(required): The paste ID to deleteconfirm(required): Set to true to confirm deletion
Example:
Please permanently delete paste xyz789 and confirm you want to do this.
Claude Desktop Configuration
Add this to your Claude Desktop configuration:
{
"mcpServers": {
"pasto": {
"transport": "http",
"url": "https://your-pasto-instance.com/mcp",
"headers": {
"Authorization": "Bearer pasto_ak_xxxxxxxxxxxx"
}
}
}
}
Usage Examples
Creating a Paste
User: Create a paste with this Rust code:
fn main() {
println!("Hello, Pasto!");
}
Claude: I'll create a paste with that Rust code for you.
✅ Paste created successfully!
🔗 URL: https://your-pasto-instance.com/abc123
📝 ID: abc123
🏷️ Title: Untitled
🔐 Private: false
🔒 Encrypted: false
Listing Your Pastes
User: Show me my recent pastes
Claude: 📄 **Your Pastes (Page 1 of 1)**
📊 Total: 5 pastes | Showing: 20 per page
🌐 **My Rust Script** (abc123)
🔤 rust
📅 2024-12-22T10:30:00Z
⏰ Never expires
🔐**Secret Algorithm** (def456)
🔒 python
📅 2024-12-21T15:45:00Z
⏰ Expires: 2024-12-28T15:45:00Z
Security
- Authentication Required: All MCP requests require valid API keys
- Permission Control: Users can only access their own pastes
- Rate Limiting: MCP endpoints respect existing rate limits
- HTTPS Recommended: Use HTTPS in production environments
Troubleshooting
Authentication Errors: Ensure your API key starts with pasto_ak_ and is valid.
Permission Denied: Make sure you're trying to access your own pastes.
Not Found: Verify the paste ID exists and hasn't expired.
Supported Languages
Pasto supports 35+ programming languages including:
- Popular: Python, JavaScript, TypeScript, Java, C, C++, C#, Go, Rust
- Web: HTML, CSS, SCSS, Sass, JSON, XML, YAML, Markdown
- Systems: Bash, Shell, PowerShell, Dockerfile
- Data: SQL, MySQL, PostgreSQL, CSV
- And more: PHP, Ruby, Perl, Kotlin, Scala, ActionScript...
Only languages with working Tartrazine lexers are available.
Theme Support
UI Themes (Pico CSS)
- 15 color schemes: Slate, Zinc, Gray, Neutral, Stone, Red, Orange, Amber, Yellow, Lime, Green, Emerald, Cyan, Sky, Indigo, Violet, Fuchsia, Pink
- Light/Dark/Auto modes with system preference detection
Syntax Themes (Tartrazine)
- 321+ themes including popular ones like Dracula, Monokai, Nord, Solarized, One Dark, GitHub, VS Code themes, and many more
Project Structure
pasto/
├── src/
│ ├── pasto.cr # Entry point, configuration
│ ├── server.cr # Kemal routes and middleware
│ ├── paste.cr # Paste model, highlighting, themes
│ ├── pasto_ssh.cr # SSH server entry point
│ └── views/
│ ├── layout.ecr # Main layout with sidebar
│ ├── index.ecr # Create paste page
│ ├── show.ecr # View paste page
│ ├── edit.ecr # Edit paste page
│ ├── history.ecr # Version history page
│ └── profile_content.ecr # User profile
├── data/ # Sepia storage directory
├── public/cache/ # Cached rendered pastes
├── sessions/ # Session storage
└── pasto.yml # Configuration file
Development
# Install dependencies
shards install
# Build
shards build
# Build release
shards build --release
# Run tests
crystal spec
# Format code
crystal tool format src/
# Lint
./bin/ameba src/
Security Features
- Rate Limiting: Configurable per-IP rate limits
- Size Validation: Maximum paste size enforcement
- HTML Escaping: All content properly sanitized
- Session Security: Secure cookie-based sessions
- SSH Key Auth: Public key authentication for SSH access
Dependencies
- Kemal: Web framework
- Tartrazine: Syntax highlighting (321+ themes)
- Hansa: Language classification
- Sepia: Object persistence with versioning
- Shirk: SSH server
- Pico CSS: Minimal CSS framework
- Lucide: Icon library
- CodeJar: Code editor
License
MIT License - see LICENSE for details.
Author
Created by Roberto Alsina
Pasto - Modern pastebin with SSH access and live preview.
Public Instance
A public Pasto instance is available at https://pasto1.ralsina.me.
pasto
- 26
- 1
- 0
- 0
- 11
- 5 days ago
- November 25, 2025
MIT License
Thu, 08 Jan 2026 22:55:23 GMT