# ============================================================================= # Hoodik — configuration reference # Copy this file to .env and adjust for your environment. # All values shown are the defaults unless marked as *required*. # ============================================================================= # ----------------------------------------------------------------------------- # Core # ----------------------------------------------------------------------------- # Directory where all uploaded files and the database will be stored. # There is no default — this must be set before starting the application. DATA_DIR=/tmp/data # PostgreSQL connection string. Omit to use the built-in SQLite database. # WARNING: SQLite and PostgreSQL are not interchangeable. Switching after data # has been written will result in data loss. # DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres # Port the server listens on. (default: 5443) # HTTP_PORT=5443 # IP address the server binds to. # In the Docker image this is automatically set to 0.0.0.0. # Only change this if you are running the binary directly outside of Docker. # (default: localhost) # HTTP_ADDRESS=localhost # Public URL of the application. Used for generating links in emails and for # CORS/cookie configuration. Set this to your actual domain in production. # (default: https://{HTTP_ADDRESS}:{HTTP_PORT}) APP_URL=https://localhost:5443 # URL of the web frontend. In production this should match APP_URL. # During development, point this at the Vite dev server (http://localhost:5173). # Also used for action links inside emails. # (default: APP_URL) APP_CLIENT_URL=http://localhost:5173 # Number of HTTP worker threads. When unset, one worker is spawned per CPU # core. Set this to cap the thread count on small or shared hosts. # WORKERS=2 # ----------------------------------------------------------------------------- # TLS # ----------------------------------------------------------------------------- # Disable TLS entirely. For development and testing only. # (default: false) # SSL_DISABLED=true # Path to a PEM-encoded TLS certificate. # If neither cert nor key is provided, a self-signed certificate is generated # automatically in DATA_DIR. Not recommended for production. # (default: DATA_DIR/hoodik.crt.pem) # SSL_CERT_FILE=/path/to/cert.crt.pem # Path to the PEM-encoded TLS private key matching SSL_CERT_FILE. # (default: DATA_DIR/hoodik.key.pem) # SSL_KEY_FILE=/path/to/key.key.pem # ----------------------------------------------------------------------------- # Authentication & sessions # ----------------------------------------------------------------------------- # Secret used to sign JWT tokens. # If not set, a random secret is generated on every startup, which invalidates # all existing sessions whenever the application restarts. # Set this to a stable random string in production. # JWT_SECRET=change-me-to-a-long-random-string # How many days an idle session remains valid before requiring a new login. # (default: 30) # LONG_TERM_SESSION_DURATION_DAYS=30 # Lifetime in seconds of the short-lived access token. # The token is refreshed automatically while the user is active. # (default: 120) # SHORT_TERM_SESSION_DURATION_SECONDS=120 # Name of the session cookie. # (default: hoodik_session) # SESSION_COOKIE=hoodik_session # Name of the refresh token cookie. # (default: hoodik_refresh) # REFRESH_COOKIE=hoodik_refresh # Hide the session cookie from JavaScript (recommended). # (default: true) # COOKIE_HTTP_ONLY=true # Only send cookies over HTTPS (recommended). # (default: true) # COOKIE_SECURE=true # SameSite cookie policy. Valid values: Lax, Strict, None. # Set to None if your frontend and backend are on different domains (also # requires COOKIE_SECURE=true). # (default: Lax) # COOKIE_SAME_SITE=Lax # Override the cookie domain. Defaults to the host from APP_URL. # Only change this if you know what you are doing — a wrong value will break # authentication. # COOKIE_DOMAIN=example.com # Use Authorization headers instead of cookies for authentication. # # Enable this when your frontend and backend are on different domains, or when # you need to access the API from a separate application. # # When enabled: # - Tokens are stored in the browser's localStorage (not HttpOnly cookies). # - Every request must include the token via: Authorization: Bearer # - Tokens are accessible to JavaScript, which increases XSS risk. # # Leave this at false (the default) when running on a single domain. # (default: false) # USE_HEADERS_FOR_AUTH=false # ----------------------------------------------------------------------------- # Email (SMTP) # ----------------------------------------------------------------------------- # Email provider. Set to "smtp" to enable, or leave empty / set to "none" to # disable. When disabled, new accounts are activated automatically without # email confirmation — suitable for local or private deployments. # (default: none) # MAILER_TYPE=none # The following variables are required when MAILER_TYPE=smtp: # SMTP_ADDRESS=smtp.gmail.com # SMTP_USERNAME=you@gmail.com # SMTP_PASSWORD=your-app-password # SMTP port. TLS mode is auto-detected from the port if SMTP_TLS_MODE is not set: # 465 → implicit TLS (default) # 587 → STARTTLS # 25 → plain (no TLS) # (default: 465) # SMTP_PORT=465 # Force a specific TLS mode. Valid values: implicit, starttls, none. # If not set, the mode is auto-detected from SMTP_PORT. # SMTP_TLS_MODE=implicit # Sender email address shown in outgoing emails. # SMTP_DEFAULT_FROM_EMAIL=you@gmail.com # Sender display name (optional). Defaults to "Hoodik" if not set. # SMTP_DEFAULT_FROM_NAME=Hoodik Drive # ----------------------------------------------------------------------------- # Storage provider # ----------------------------------------------------------------------------- # Which backend to use for storing file chunks. # Valid values: local, s3 # (default: local) # STORAGE_PROVIDER=local # Refuse `?format=tar`, so clients move a file's chunks one request at a time # instead of bundling them into a single archive. # # The archive is an optimisation — one request instead of one per chunk — and # it is the wrong one behind a proxy that caps request size. Cloudflare Tunnel # stops at 100 MB, and a tar above that dies there while the same file # transfers fine a chunk at a time. Applies to both directions, and to local # and S3 storage alike. # # Phrased as a disable so leaving it unset keeps the faster path. # TAR_TRANSFER_DISABLED=false # The following variables are required when STORAGE_PROVIDER=s3: # S3 bucket name where file chunks will be stored. # S3_BUCKET=my-hoodik-bucket # AWS region. (default: us-east-1) # S3_REGION=us-east-1 # Custom S3 endpoint for S3-compatible services (MinIO, Backblaze B2, Wasabi, # DigitalOcean Spaces, etc.). Omit for standard AWS S3. # S3_ENDPOINT=http://localhost:9000 # Access key ID and secret key for S3 authentication. # S3_ACCESS_KEY=your-access-key # S3_SECRET_KEY=your-secret-key # Use path-style addressing (required for MinIO and some S3-compatible services). # (default: false) # S3_PATH_STYLE=false # Optional key prefix for all objects (e.g. "hoodik/" to namespace within a # shared bucket). # S3_PREFIX= # Let clients read and write chunks straight from the bucket over signed URLs, # so file data stops passing through this server in either direction. # (default: false) # # This only works if your bucket is usable by the CLIENT, not just by this # server: reachable from outside, over HTTPS, with a publicly trusted # certificate, and with a CORS policy allowing APP_URL for GET and PUT. The # endpoint above (http://localhost:9000) is an example of a setup that cannot # do it — no client resolves it, and browsers refuse plain HTTP from an HTTPS # page. # # Hoodik checks all of that at startup, including a real CORS preflight. If # anything fails it logs why, leaves this off, and keeps relaying transfers. # See /api/readiness for the verdict, and README "Direct transfer" for detail. # S3_DIRECT_TRANSFER=false # How long a signed chunk URL stays valid, in seconds. (default: 604800) # All of a transfer's URLs are signed up front so a mobile client can hand the # whole set to the OS and be suspended for as long as the transfer takes, which # is why the default is the 7-day maximum SigV4 allows. Each URL is a bearer # token for one chunk of ciphertext and is useless without the file key. # S3_DIRECT_EXPIRY_SECS=604800 # Skip the HTTPS, certificate and private-address checks above. For a bucket on # your own network with clients on that same network (a home NAS). CORS is still # required — browsers enforce it wherever the bucket sits. (default: false) # S3_DIRECT_ALLOW_INSECURE=false # ----------------------------------------------------------------------------- # Storage limits # ----------------------------------------------------------------------------- # Hard ceiling, in bytes, on the total stored across the whole instance # (summed over every account), independent of any per-user quota. Enforced at # every upload. Omit for no instance-wide limit. # STORAGE_INSTANCE_QUOTA_BYTES=107374182400