Skip to content

naste

A minimal, self-hosted paste service for the command line. No database. No frameworks. Just files.

Host your own for privacy or provide it as a free service to others.

At a Glance

Language Go (stdlib only, zero dependencies)
Storage Filesystem (no database)
Binaries naste-server (server), naste (CLI client)
Deployment Docker, Nix, NixOS module, Home Manager module
Security Path traversal prevention, atomic writes, constant-time auth
Size limit 10 MB per paste

Quick Start

CLI Client

The naste binary sends text to a paste server and returns a URL. Install it on any machine to push pastes.

go install github.com/semi710/naste/cmd/naste@latest
echo "hello world" | naste
echo "hello world" | nix run github:semi710/naste#naste --
programs.naste-client = {
  enable = true;
  endpoint = "https://paste.semi.sh";
};
programs.naste-client = {
  enable = true;
  endpoint = "https://paste.semi.sh";
};

Server

The naste-server binary hosts the paste service on port 8080. It stores pastes as files on disk. No database, no dependencies.

docker run -d \
  --name naste \
  -p 8080:8080 \
  -v /var/lib/naste/data:/data/paste \
  ghcr.io/semi710/naste-server:latest
# Default settings (port 8080, data in /data/paste)
nix run github:semi710/naste#naste-server

# With custom env vars
PORT=9090 DATA_DIR=/tmp/naste-data nix run github:semi710/naste#naste-server
go build -o naste-server .
PORT=8080 DATA_DIR=./data ./naste-server
services.naste-server = {
  enable = true;
  port = 8080;
  openFirewall = true;
};
services.naste-server = {
  enable = true;
  port = 8080;
};

Usage

# Pipe any text
echo "hello world" | naste
# -> https://paste.semi.sh/abc123

# With a custom slug
cat deploy.sh | naste --slug deploy

# Private paste (requires server auth config)
cat secrets.env | naste --private --slug secrets

# Force overwrite existing slug
naste updated.go --force --slug mycode

# Auto-detects language from file extension
naste main.go

Features

  • Zero Database - Filesystem-based storage. No PostgreSQL, no MongoDB, no Redis.
  • Private Pastes - HTTP Basic Auth for sensitive content. No accounts needed.
  • Custom Slugs - Readable URLs like /deploy-script instead of random IDs.
  • Syntax Highlighting - Auto-detects language from file extension. Dark theme in browser.
  • Single Binary - One Go binary. Deploy anywhere in seconds.
  • Docker Ready - Multi-arch images (amd64 + arm64) via GitHub Actions.
  • NixOS Module - Declarative system service with sops-nix secret support.
  • Home Manager - Run as a user service, no root required.

Architecture

                    +-------------+
                    |   naste     |  CLI client
                    |  (binary)   |  reads ~/.config/naste/config.toml
                    +-----+-------+
                          |
                    POST /api/paste
                    GET  /{slug}
                          |
                    +-----+-------+
                    | naste-server|  HTTP server
                    |  (binary)   |  port 8080
                    +-----+-------+
                          |
                    +-----+-------+
                    | filesystem  |  /data/paste/
                    |  storage    |  public/ private/ metadata/
                    +-------------+

The server stores pastes as flat files in three directories:

  • public/ - public paste content
  • private/ - private paste content (auth-gated)
  • metadata/ - JSON metadata per paste (slug, lang, size, timestamps)

All writes are atomic (temp file + rename). No partial states.

Configuration

The CLI reads configuration from (in order of precedence):

  1. PASTE_ENDPOINT env var
  2. PASTE_USER / PASTE_PASS / PASTE_USER_FILE / PASTE_PASS_FILE env vars
  3. ~/.config/naste/config.toml
  4. Built-in default: https://paste.semi.sh
# ~/.config/naste/config.toml
endpoint = "https://paste.semi.sh"
user = "admin"
password = "secret"

Documentation