bin/README.md
2025-11-30 18:20:47 -05:00

435 lines
No EOL
10 KiB
Markdown

# Bin Pastebin Nix Flake
This flake provides a Nix package and NixOS module for [bin](https://github.com/wantguns/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:
```nix
{
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:
```nix
{
services.bin = {
enable = true;
port = 6162;
address = "127.0.0.1";
};
}
```
### Complete Configuration Example
```nix
{
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:
```nix
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:
```bash
# 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:
```bash
# 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`:
```vim
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
```bash
# View service logs
sudo journalctl -u bin -f
# View nginx logs (if using reverse proxy)
sudo journalctl -u nginx -f
```
### Managing Uploads
```bash
# 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
```bash
# 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:
```nix
{
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:
```nix
{
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:
```nix
{
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:
```bash
# 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
```bash
# 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:
```bash
# 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
- Original bin project: https://github.com/wantguns/bin
- Based on Rocket framework: https://rocket.rs/