No description
Find a file
2025-11-30 18:37:24 -05:00
.gitignore Fix hashes 2025-11-30 18:37:24 -05:00
flake.lock Fix hashes 2025-11-30 18:37:24 -05:00
flake.nix Fix hashes 2025-11-30 18:37:24 -05:00
README.md Initial commit 2025-11-30 18:20:47 -05:00

Bin Pastebin Nix Flake

This flake provides a Nix package and NixOS module for bin, a minimal pastebin service that accepts binary files like images and PDFs.

Features

  • Minimal and fast: Written in Rust using the Rocket framework
  • Binary file support: Upload images, PDFs, and other binary files
  • Multiple clients: Web UI, CLI, and Vim integration
  • Self-contained: No external database required
  • Security hardened: Systemd service with strict security policies
  • Nginx integration: Built-in reverse proxy configuration with SSL support

Quick Start

Using the Flake in Your NixOS Configuration

Add the flake to your flake.nix inputs:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    bin-flake.url = "path:/path/to/this/flake";
    # Or from GitHub (once published):
    # bin-flake.url = "github:yourusername/bin-flake";
  };

  outputs = { self, nixpkgs, bin-flake, ... }: {
    nixosConfigurations.yourhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        bin-flake.nixosModules.default
        ./configuration.nix
      ];
    };
  };
}

Basic Configuration

In your NixOS configuration:

{
  services.bin = {
    enable = true;
    port = 6162;
    address = "127.0.0.1";
  };
}

Complete Configuration Example

{
  services.bin = {
    enable = true;
    
    # Network settings
    address = "127.0.0.1";
    port = 6162;
    openFirewall = false;  # Set to true if not using nginx
    
    # Storage settings
    uploadDir = "/var/lib/bin/upload";
    binaryUploadLimit = 100;  # MiB
    
    # UI settings
    clientDescription = true;  # Show CLI client info on landing page
    
    # Custom environment variables
    environmentFile = pkgs.writeText "bin-env" ''
      BIN_LIMITS={form="16 MiB"}
      BIN_WORKERS=8
      BIN_IDENT=false
      BIN_KEEP_ALIVE=5
      BIN_LOG_LEVEL=normal
    '';
    
    # Nginx reverse proxy
    nginx = {
      enable = true;
      domain = "paste.yourdomain.com";
      enableSSL = true;  # Uses Let's Encrypt
    };
  };
  
  # Ensure nginx and ACME are configured
  services.nginx.enable = true;
  security.acme = {
    acceptTerms = true;
    defaults.email = "admin@yourdomain.com";
  };
}

Configuration Options

Core Options

Option Type Default Description
enable bool false Whether to enable the bin service
package package bin The bin package to use
user string "bin" User account under which bin runs
group string "bin" Group under which bin runs

Network Options

Option Type Default Description
address string "127.0.0.1" Address on which the webserver listens
port int 6162 Port on which the webserver listens
openFirewall bool false Whether to open the firewall for the service

Storage Options

Option Type Default Description
uploadDir path "/var/lib/bin/upload" Directory where uploaded pastes are stored
binaryUploadLimit int 100 Binary uploads file size limit (in MiB)

Feature Options

Option Type Default Description
clientDescription bool true Whether to show the /client description on landing page
extraArgs list of strings [] Extra command-line arguments to pass to bin
environmentFile null or path null File containing environment variables for bin

Nginx Options

Option Type Default Description
nginx.enable bool false Whether to enable nginx reverse proxy
nginx.domain string "paste.example.com" Domain name for the bin service
nginx.enableSSL bool true Whether to enable SSL (uses ACME/Let's Encrypt)

Environment Variables

The bin service supports additional configuration through environment variables. You can set these using the environmentFile option:

environmentFile = pkgs.writeText "bin-env" ''
  # Rocket configuration
  BIN_LIMITS={form="16 MiB"}      # Form data size limit
  BIN_WORKERS=8                    # Number of worker threads
  BIN_IDENT=false                  # Disable server identification
  BIN_KEEP_ALIVE=5                 # Keep-alive timeout in seconds
  BIN_LOG_LEVEL=normal             # Log level: off, critical, normal, debug
  
  # Additional Rocket settings
  BIN_SECRET_KEY=your-secret-key   # For encrypted cookies (generate with openssl)
  BIN_TLS={certs="path/to/certs",key="path/to/key"}  # TLS configuration
'';

Client Configuration

Web Client

Access the web interface at http://localhost:6162 (or your configured domain).

CLI Client

The CLI client can be installed and configured:

# Download the client
curl -o ~/.local/bin/pst https://yourdomain.com/client
chmod +x ~/.local/bin/pst

# Or create your own client script
cat > ~/.local/bin/pst << 'EOF'
#!/bin/bash
URL="https://paste.yourdomain.com"
FILEPATH="$1"
FILENAME=$(basename -- "$FILEPATH")
EXTENSION="${FILENAME##*.}"

RESPONSE=$(curl --data-binary @${FILEPATH:-/dev/stdin} --url $URL)
PASTELINK="$URL$RESPONSE"

[ -z "$EXTENSION" ] && \
    echo "$PASTELINK" || \
    echo "$PASTELINK.$EXTENSION"
EOF
chmod +x ~/.local/bin/pst

Usage:

# Upload a file
pst somefile.txt

# Pipe content
echo "Hello, World!" | pst

# Upload an image
pst screenshot.png

Vim Integration

Add to your init.vim or .vimrc:

nnoremap <leader>p :!pst %<CR>

Security Considerations

The NixOS module implements several security measures:

  1. Systemd Hardening: The service runs with strict sandboxing
  2. Separate User: Runs under a dedicated system user
  3. Filesystem Isolation: Only the upload directory is writable
  4. Network Restrictions: Limited to IPv4/IPv6 address families
  5. System Call Filtering: Restricted to necessary system calls

Maintenance

Viewing Logs

# View service logs
sudo journalctl -u bin -f

# View nginx logs (if using reverse proxy)
sudo journalctl -u nginx -f

Managing Uploads

# View disk usage
du -sh /var/lib/bin/upload

# Clean old uploads (example: files older than 30 days)
find /var/lib/bin/upload -type f -mtime +30 -delete

# Backup uploads
tar -czf bin-uploads-$(date +%Y%m%d).tar.gz /var/lib/bin/upload

Service Management

# Restart the service
sudo systemctl restart bin

# Check service status
sudo systemctl status bin

# Reload after configuration changes
sudo nixos-rebuild switch

Advanced Usage

Custom Nginx Configuration

If you need more control over the nginx configuration:

{
  services.bin = {
    enable = true;
    nginx.enable = false;  # Disable automatic nginx config
  };
  
  services.nginx.virtualHosts."paste.yourdomain.com" = {
    enableACME = true;
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://127.0.0.1:6162";
      extraConfig = ''
        client_max_body_size 100M;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # Custom headers
        proxy_set_header X-Custom-Header "value";
        
        # Rate limiting
        limit_req zone=paste burst=5 nodelay;
      '';
    };
  };
}

Running Multiple Instances

You can run multiple bin instances on different ports:

{
  services.bin = {
    enable = true;
    port = 6162;
    uploadDir = "/var/lib/bin/upload";
  };
  
  # Second instance (requires manual systemd service)
  systemd.services.bin-private = {
    description = "Private bin instance";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      ExecStart = "${pkgs.bin}/bin/bin --port 6163 --upload /var/lib/bin-private/upload";
      User = "bin-private";
      Group = "bin-private";
      StateDirectory = "bin-private";
    };
  };
  
  users.users.bin-private = {
    isSystemUser = true;
    group = "bin-private";
  };
  users.groups.bin-private = {};
}

Integration with Monitoring

Example Prometheus/Grafana integration:

{
  services.prometheus = {
    enable = true;
    scrapeConfigs = [{
      job_name = "bin";
      static_configs = [{
        targets = [ "localhost:6162" ];
      }];
    }];
  };
  
  services.grafana.provision.dashboards = [{
    options.path = ./dashboards;
    # Add your bin dashboard JSON here
  }];
}

Troubleshooting

Service Won't Start

  1. Check logs: sudo journalctl -u bin -e
  2. Verify permissions: ls -la /var/lib/bin
  3. Check port availability: sudo ss -tlnp | grep 6162

Upload Errors

  1. Check file size limits in configuration
  2. Verify disk space: df -h /var/lib/bin
  3. Check nginx client_max_body_size if using reverse proxy

SSL Certificate Issues

  1. Ensure domain points to your server
  2. Check ACME logs: sudo journalctl -u acme-paste.yourdomain.com
  3. Verify ports 80/443 are accessible

Development

To work on the bin source code:

# Enter development shell
nix develop

# Run locally
cargo run -- --address 127.0.0.1 --port 6162

# Run tests
cargo test

# Format code
cargo fmt

# Lint
cargo clippy

Building

Build the package

# Build the bin package
nix build .#bin

# Build the Docker image
nix build .#docker

# Load Docker image
docker load < result

Cross-compilation

The flake supports cross-compilation:

# Build for aarch64-linux on x86_64-linux
nix build .#packages.aarch64-linux.bin

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Test your changes thoroughly
  4. Submit a pull request

License

This flake is provided under the same license as the bin project (LGPL-3.0).

Credits