Skip to content

Latest commit

 

History

History
167 lines (129 loc) · 6.23 KB

File metadata and controls

167 lines (129 loc) · 6.23 KB

Configuration

Snapshot reads configuration from environment variables and .env.

Start by copying the example file:

cp .env.example .env

PowerShell:

Copy-Item .env.example .env

Generate a strong API key:

python -c "import secrets; print(secrets.token_urlsafe(48))"

Use the generated value as API_KEY.

Environment Variables

Variable Default Description
ENVIRONMENT development Set to production for stricter startup validation
HOST 0.0.0.0 Bind address used by Uvicorn
PORT 3000 HTTP port
BASE_URL http://localhost:3000 Public base URL returned after uploads
API_KEY required API key required for upload, list, and delete
STORAGE_DIR /app/data/uploads in Docker Directory where uploaded files are stored
PUBLIC_DIR public Directory for optional static public assets
MAX_FILE_SIZE_BYTES 52428800 Maximum accepted upload size
UPLOAD_CHUNK_SIZE_BYTES 1048576 Streaming read/write chunk size
FILE_ID_LENGTH 10 Length of generated public file IDs
ALLOWED_EXTENSIONS see .env.example Comma-separated allowed extensions
ALLOWED_MIME_TYPES see .env.example Comma-separated allowed MIME types
CORS_ORIGINS * Comma-separated CORS origins
ALLOWED_HOSTS * Comma-separated trusted host names
HEALTHCHECK_HOST localhost Host header used by the Docker healthcheck
ENABLE_DOCS true Enables /docs, /redoc, and /openapi.json
HSTS_ENABLED false Enables Strict-Transport-Security for HTTPS deployments
RATE_LIMIT_ENABLED true Enables rate limiting
RATE_LIMIT_REQUESTS 120 Requests allowed per rate-limit window
RATE_LIMIT_WINDOW_SECONDS 60 Rate-limit window length
LOG_LEVEL INFO Python logging level
LOG_FILE empty in Docker Optional rotating log file path. Empty disables file logging
SHAREX_CONFIG_ENABLED true Generates a ShareX .sxcu file on startup
EMBED_ENABLED true Emits Open Graph and Twitter Card metadata on the HTML page
EMBED_PROVIDER_NAME Snapshot Provider name used in og:site_name and the {provider} template variable
EMBED_TITLE_TEMPLATE {filename} Template for og:title / twitter:title
EMBED_DESCRIPTION_TEMPLATE Uploaded with Snapshot Template for og:description / twitter:description
EMBED_THEME_COLOR #5865F2 Accent and theme-color. Must match ^#[0-9A-Fa-f]{6}$
EMBED_LOCALE en_US Value used for og:locale and the page language
TIMEZONE UTC IANA time zone (e.g. Europe/Berlin) used to display {created_at} and the on-page upload time

Page branding (brand name/logo, <title> template, on-page description, footer, and custom CSS) is fixed in code and is not configurable.

Public Delivery and Embeds

GET /{id} always returns a clean, extension-less URL (https://img.example.com/<id>) that renders a responsive HTML preview page with Open Graph and Twitter Card metadata for Discord and other platforms, with the Download button, Original link, and file metadata block always shown. The raw file is always available at https://img.example.com/raw/<id>.<ext> — use that URL directly if you only want the file, with ?download=1 forcing a download via Content-Disposition: attachment. Cache-Control headers are fixed: public, max-age=31536000, immutable for raw files and public, max-age=300 for the HTML page.

GET /{id}.{ext} is a compatibility route for old extension-based links: it looks up the file by id (ignoring the extension you pass) and, if found, responds with 301 Moved Permanently to the clean /{id} URL. Unknown ids return 404. There is no separate delete route for this path — delete via DELETE /raw/{id}.{ext}.

Only the embed metadata (EMBED_*) and TIMEZONE are configurable — the delivery mode and cache headers are not.

The embed title/description templates accept only these variables:

{id} {filename} {extension} {content_type} {size} {size_human} {created_at} {provider}

{created_at} and the on-page upload time are formatted as a human-readable date/time in EMBED_LOCALE and converted to TIMEZONE (falling back to en_US / UTC if either is invalid or unrecognized). Startup fails fast if TIMEZONE is not a valid IANA time zone name.

Unknown variables (or attribute-style expressions such as {file.__dict__}) are rejected at startup, and every rendered value is HTML-escaped.

Version Check

The release version check uses fixed internal defaults instead of environment variables. Snapshot checks in the background every 10 minutes, keeps the cached result for 10 minutes, applies a 60 second cooldown to all GitHub fetch attempts, and uses a 3 second request timeout.

Production Recommendations

Use stricter values for public deployments:

BASE_URL=https://img.example.com
CORS_ORIGINS=https://example.com
ALLOWED_HOSTS=img.example.com,localhost,127.0.0.1
HEALTHCHECK_HOST=localhost
ENABLE_DOCS=false
HSTS_ENABLED=true
ENVIRONMENT=production

Keep these files and directories private:

  • .env
  • data/
  • *.log

They are already ignored by .gitignore.

Storage and Logs

STORAGE_DIR=/app/data/uploads points to the container path. The repository Compose file and README docker run quickstart mount ./data to /app/data:

./data/uploads -> /app/data/uploads
./data/snapshot.sxcu -> /app/data/snapshot.sxcu

Outside Docker, Snapshot writes snapshot.sxcu to the current working directory. In Docker, it writes /app/data/snapshot.sxcu, which appears on the host as data/snapshot.sxcu.

Manual files in data/uploads are supported when their filename stem contains only letters, numbers, dots, underscores, and hyphens. Examples:

summer-2026.png
dashboard_01.webp

LOG_FILE= disables rotating file logs. This is the recommended Docker default because logs are available through:

docker compose logs -f
docker compose logs --no-color > snapshot.log

If you explicitly want file logs, mount a log directory and set LOG_FILE:

volumes:
  - ./data:/app/data
  - ./data/logs:/app/logs
LOG_FILE=/app/logs/snapshot.log