Skip to content

coalaura/echo-vault

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

163 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

banner

A blazing fast, minimal ShareX backend written in Go. Echo-Vault features a powerful, configurable media processing pipeline and a built-in, dependency-free dark mode dashboard. It leverages ffmpeg and gifsicle to handle transcoding and optimization, keeping the core service lean while giving you full control over your media.

Features

  • Drop-in ShareX uploader with bearer-token auth
  • Minimal, responsive Web UI for gallery viewing and management
  • Find screenshots by describing them ("blue car", "internet speed test") using local vector embeddings
  • Automatically generates metadata and tags for images via OpenRouter (LLMs)
  • Scheduled tar.gz snapshots of your database and media files with configurable retention policies
  • Configurable image processing to WebP, PNG, or JPEG
  • Video transcoding and optimization (MP4, WebM, etc.) powered by ffmpeg
  • Advanced GIF pipeline: convert from video, resample, downscale, reduce colors, and optimize with gifsicle
  • Import existing files straight into the database with the scan command
  • Smart background backfilling for existing uploads
  • Commented config.yml generated on first run

example

Installation

  1. Download the latest release or build from source.
  2. Install dependencies. ffmpeg and ffprobe are required for video/GIF features.
# Debian/Ubuntu
sudo apt install ffmpeg

# Arch Linux
sudo pacman -S ffmpeg

If you are using the AI-enabled version (for semantic screenshot search), you must set up the onnx/ directory structure next to your executable.

The final folder layout should look like this:

echo_vault (or echo_vault.exe)
onnx/
├── lib/
│   └── libonnxruntime.so (or onnxruntime.dll)
└── models/
    ├── clip_tokenizer/
    │   ├── tokenizer.json
    │   └── tokenizer_config.json
    ├── clip_text.onnx
    ├── clip_text.onnx.data
    ├── clip_visual.onnx
    └── clip_visual.onnx.data

Follow these steps to set it up:

  1. Download the Binary: Choose either echo_vault_linux-amd64_ai or echo_vault_windows-amd64_ai.exe and rename it to echo_vault (or echo_vault.exe).

  2. Download & Extract Models: Download clip_model.tar.gz from the release assets and extract it inside the same directory as the binary. This automatically creates the onnx/models/ folder.

  3. Install ONNX Runtime: Download the appropriate shared library (v1.16.0+ recommended) for your platform from the ONNX Runtime Releases:

    • Windows: Download onnxruntime-win-x64-<version>.zip, extract onnxruntime.dll and place it in onnx/lib/onnxruntime.dll.
    • Linux: Download onnxruntime-linux-x64-<version>.tgz, extract libonnxruntime.so.<version>, rename/symlink it to libonnxruntime.so and place it in onnx/lib/libonnxruntime.so.
  4. Run the binary once in the target directory to create config.yml and storage/.

  5. Edit config.yml to enable features and set your domain, port, and upload token.

  6. (Optional) Install the provided echo_vault.service unit next to the binary.

  7. Make the binary executable: chmod +x echo_vault.

  8. Update the service file paths, symlink it into /etc/systemd/system/, and start it (service echo_vault start).

  9. Point nginx (or another reverse proxy) at the backend (config below).

  10. Configure ShareX to send uploads to your instance using the bearer token.

sharex

Configuration

Running Echo-Vault creates a commented config.yml. Adjust it and restart the service.

server:
  # base url of your instance (default: http://localhost:8080/)
  url: http://localhost:8080/
  # port to run echo-vault on (default: 8080)
  port: 8080
  # only append the filename to the base url, no "/i/" (for custom endpoints; default: false)
  direct: false
  # upload token for authentication, leave empty to disable auth (default: p4$$w0rd)
  token: p4$$w0rd
  # maximum upload file-size in MB (default: 20MB)
  max_file_size: 20
  # maximum concurrent uploads (default: 4)
  max_concurrency: 4
  # if echos without their file should be deleted (default: false)
  delete_orphans: false

backup:
  # if backups should be created (default: true)
  enabled: true
  # how often backups should be created (in hours; default: 120)
  interval: 120
  # how many backups to keep before deleting the oldest (default: 4)
  keep_amount: 4
  # if files (images/videos) should be included in backups (without, only the database is backed up; default: true)
  backup_files: true

images:
  # target format for images (webp, png or jpeg; default: webp)
  format: webp
  # quality/speed trade-off (1 = fast/big, 2 = medium, 3 = slow/small; default: 2)
  effort: 2
  # webp quality (0-100, 100 = lossless; default: 90)
  quality: 90

videos:
  # allow video uploads (requires ffmpeg; default: false)
  enabled: false

gifs:
  # allow gif uploads (requires ffmpeg when using gif as target; default: true)
  enabled: true
  # target format for gifs (gif or webp; default: webp)
  format: webp

API & Nginx

The application serves the Dashboard at /, API endpoints at /echos and /upload, and raw files at /i/.

To support the Web UI, Nginx should proxy requests to the backend. You can still serve storage files directly via Nginx for maximum performance if desired.

# Serve images directly (optional, for performance)
location /i/ {
    alias /path/to/your/storage/;

    etag on;
    expires 30d;

    location ~* \.(mp4|webm|mov|mkv|m4v)$ {
        add_header Accept-Ranges bytes always;

        output_buffers 2 1m;
    }
}

# Proxy UI and API
location / {
    proxy_pass       http://localhost:8080;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host            $host;

    # Required for large uploads
    client_max_body_size 100M;
}

Custom Image Domains (/not_found)

If you host your images on a separate custom domain (e.g., i.example.com) and serve them directly via Nginx, users visiting the root / of your image domain will hit an empty directory index, and broken links will result in generic Nginx 404 pages.

To handle this cleanly, Echo-Vault provides a generic /not_found endpoint that renders a clean, templated error page. You can configure Nginx on your image domain to fallback to this page:

# Custom Image Domain Server Block (e.g., i.example.com)
server {
    listen 80;
    server_name i.example.com;

    root /path/to/your/storage/;

    error_page 404 = @notFound;

    # Try serving files directly from your storage folder, falling back to 404
    location / {
        try_files $uri =404;

        etag on;
        expires 30d;
    }

    location @notFound {
        proxy_pass       http://localhost:8080/not_found;
        proxy_set_header Host            $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Authentication

All API routes under /upload and /echos expect Authorization: Bearer <token>. The Web UI handles this automatically via a login prompt.

GET /info

Returns the current server version and feature flags.

{
    "version": "dev",
    "queries": true
}

GET /verify

Used to check token validity. Returns 200 OK or 401 Unauthorized.

POST /upload

Upload a file via multipart form (upload=<file>). Supported types: JPEG, PNG, GIF, WebP, MP4, WebM, MOV, MKV.

{
    "change": "saved 45.28% (-1.1 MB)",
    "extension": "mp4",
    "hash": "ASODE3CEHE",
    "size": "1.4 MB",
    "sniffed": "mp4",
    "timing": {
        "read": "5.2058ms",
        "store": "5.0093ms",
        "write": "1.2276779s"
    },
    "url": "http://localhost:8080/i/ASODE3CEHE.mp4"
}

GET /echos/{page}

Returns up to 100 uploads per page (1-indexed). The tag object contains safety info. Unsafe images are blurred in the dashboard until hovered.

[
    {
        "id": 21,
        "hash": "ASODE3CEHE",
        "name": "my video.mp4",
        "extension": "mp4",
        "upload_size": 2483452,
        "timestamp": 1761174760,
        "tag": {
            "safety": "ok"
        }
    }
]

GET /query/{page}?q={query}

Semantic search endpoint. Returns results sorted by relevance. Includes a similarity score in the tag object (0.0 - 1.0).

[
    {
        "id": 45,
        "hash": "B82JSD9A2",
        "timestamp": 1761175000,
        "tag": {
            "safety": "ok",
            "similarity": 0.4281
        }
    }
]

DELETE /echos/{hash}

Removes both the file and its database entry. Replies with 200 OK.

CLI

Echo-Vault doubles as a tiny maintenance tool when invoked with commands:

echo-vault scan

Walks the storage/ directory and imports missing files into the database. Progress is logged to stdout.

About

A blazing fast minimal ShareX backend written in golang.

Resources

Stars

Watchers

Forks

Contributors