Documentation
¶
Overview ¶
Package config loads filex configuration from a YAML file with environment variable overrides (FILEX_*).
Precedence (highest first):
- Environment variables (FILEX_LISTEN, FILEX_DB_DRIVER, …)
- config.yaml (path passed via --config or default ~/.filex/config.yaml)
- Hard-coded defaults
Some settings live in the DB (settings table) instead of config.yaml — e.g. instance branding, default thumbnail policy. Those are read by individual services via db.Store.GetSetting and are NOT modeled here.
Index ¶
- Constants
- func ParseDurationDays(v string) (time.Duration, error)
- type AuthConfig
- type CORSConfig
- type CacheConfig
- type CloudConfig
- type Config
- type ConvertConfig
- type DAVConfig
- type DBConfig
- type DemoConfig
- type DrawioConfig
- type ExtServices
- type FTPSConfig
- type HeaderProxyConfig
- type LDAPConfig
- type LogConfig
- type NFSConfig
- type NotifyConfig
- type OIDCConfig
- type OnlyOfficeConfig
- type OpsConfig
- type QueueConfig
- type S3Config
- type SFTPConfig
- type SearchConfig
- type SeedConfig
- type SeedSMTP
- type SeedStorage
- type SentryConfig
- type SyncConfig
- type ThumbsConfig
- type UpdateConfig
- type UploadConfig
Constants ¶
const DefaultPublicURL = "http://localhost:5212"
DefaultPublicURL is the address filex assumes when nobody says otherwise. ⚠ It is a guess, and anything derived from it must be able to tell that it is one -- see Config.PublicURLSet.
Variables ¶
This section is empty.
Functions ¶
func ParseDurationDays ¶
ParseDurationDays is time.ParseDuration plus a `d` (day) suffix, which Go's parser lacks and which is the unit people actually write retention in. "7d" = 168h. A bare number is also accepted as days, so FILEX_SHARE_MAX_TTL=7 and =7d mean the same thing.
Types ¶
type AuthConfig ¶
type AuthConfig struct {
Drivers []string `yaml:"drivers"`
// DriversFrom says where Drivers came from: "FILEX_AUTH_DRIVERS",
// "file:<path>" or "default". The Identity providers page shows it, in
// the reader's words (authsetup.FromWords), beside every provider the
// environment defines, so an operator knows where to change one the page
// cannot (Load sets it).
DriversFrom string `yaml:"-"`
// RecoveryLogin keeps password sign-in open for the bootstrap
// administrator — and nobody else — when no `local` driver is enabled, so
// an SSO-only installation whose identity provider is down can still be
// reached by the person who has to fix it (local.RecoveryLogin). ON by
// default; FILEX_AUTH_RECOVERY_LOGIN=false turns it off.
RecoveryLogin bool `yaml:"recovery_login"`
OIDC OIDCConfig `yaml:"oidc"`
LDAP LDAPConfig `yaml:"ldap"`
Header HeaderProxyConfig `yaml:"header_proxy"`
}
AuthConfig — enabled drivers and per-driver options.
type CORSConfig ¶
type CORSConfig struct {
AllowedOrigins []string `yaml:"allowed_origins"`
AllowedMethods []string `yaml:"allowed_methods"`
AllowedHeaders []string `yaml:"allowed_headers"`
}
CORSConfig — origin allowlist.
type CacheConfig ¶
type CacheConfig struct {
// Dir is where prepared copies live. Defaults to <data_dir>/cache.
Dir string `yaml:"dir"`
// MinSize is the smallest file worth preparing (FILEX_CACHE_MIN_SIZE,
// default 64 MiB). Below it the preparation costs more than the transfer
// it saves.
MinSize int64 `yaml:"min_size"`
// MaxBytes is the GLOBAL ceiling on the cache directory
// (FILEX_CACHE_MAX_BYTES, default 20 GiB), enforced with LRU eviction. It
// is never unlimited: a per-file cache with no global cap is a disk
// incident, and this project has had one (29 GB of leaked multipart temp
// files, v0.13.4).
MaxBytes int64 `yaml:"max_bytes"`
// SlowBytesPerSec is the measured throughput below which a storage counts
// as slow (FILEX_CACHE_SLOW_BPS, default 10 MiB/s).
SlowBytesPerSec int64 `yaml:"slow_bytes_per_sec"`
// Disabled turns the whole thing off (FILEX_CACHE=0). With no slow
// storage configured it never does anything anyway.
Disabled bool `yaml:"disabled"`
// folder-share ZIP warmer pre-builds (FILEX_SHAREZIP_WARM_MAX_BYTES,
// default 2 GiB; 0 = no ceiling). Bigger folders are still zipped — on
// demand, when a visitor clicks download — they are just not built
// speculatively. See docs/SHARING.md.
ShareZipWarmMaxBytes int64 `yaml:"sharezip_warm_max_bytes"`
// before the sweeper removes it even though its share is still live
// (FILEX_SHAREZIP_MAX_AGE, default 7d; 0 = keep for the share's life).
// Accepts Go durations plus a `d` suffix ("7d", "36h").
ShareZipMaxAge time.Duration `yaml:"sharezip_max_age"`
}
CacheConfig — the local copy filex prepares for a big file that lives on a slow backend (internal/filecache). See docs/CONFIGURATION.md.
type CloudConfig ¶
type CloudConfig struct {
// Enabled is the master flag (FILEX_CLOUD=1). Default false.
Enabled bool `yaml:"enabled"`
// PlansJSON is the config-driven plan catalog (FILEX_CLOUD_PLANS), a JSON
// array of {id,name,price_monthly,stripe_price_id,limits:{storage_bytes,
// max_users}}. Empty → a single built-in "free" skeleton plan.
PlansJSON string `yaml:"plans"`
// StripeSecret is the Stripe API secret key (STRIPE_SECRET /
// FILEX_STRIPE_SECRET). Empty → billing endpoints answer 503
// "not configured".
StripeSecret string `yaml:"stripe_secret"`
// BaseHost, when set (FILEX_CLOUD_BASE_HOST, e.g. "filex.cloud"), derives
// each signed-up tenant's host as <slug>.<BaseHost>. Empty → the tenant is
// provisioned without a host (operator assigns one later).
BaseHost string `yaml:"base_host"`
}
CloudConfig — self-serve cloud/SaaS PREPARATION (v0.7 "Kimlik" E3, see docs/CLOUD.md). Master-gated by Enabled (FILEX_CLOUD): while it is false — the default — nothing in the cloud package is constructed, no /api/cloud route registers, capabilities carry no cloud field and the migration-00021 columns stay untouched. This is a skeleton for a FUTURE hosted offering, not a live service.
type Config ¶
type Config struct {
Listen string `yaml:"listen"`
PublicURL string `yaml:"public_url"`
// PublicURLSet reports whether the operator actually chose PublicURL,
// rather than inheriting DefaultPublicURL.
//
// ⚠ It matters because the default is a GUESS and filex hands it out as
// fact: the realtime ticket derives `ws_url` from it, so an instance on any
// other port told every browser to connect to :5212, the connection was
// refused, and the client fell back to 12-second polling with no error
// raised anywhere. Not serialised -- it describes how the config was
// loaded, not the deployment.
PublicURLSet bool `yaml:"-"`
DataDir string `yaml:"data_dir"`
DefaultLocale string `yaml:"default_locale"`
// CookieDomain sets the Domain attribute on the filex_session cookie
// (e.g. ".example.com" to share the session across subdomains). Empty =
// host-only cookie, the historical behavior. Applied on both set and
// clear so logout removes the same cookie it created.
CookieDomain string `yaml:"cookie_domain"`
// MultiTenant turns on native multi-tenancy (host-resolved provider =
// tenant, per-provider storage confinement, scoped user directory). OFF by
// default — a single-tenant install behaves exactly as before. See
// docs/MULTI-TENANCY.md.
MultiTenant bool `yaml:"multi_tenant"`
// PluginsDisabled (FILEX_PLUGINS_DISABLED=1) turns the storage-plugin
// subsystem off: nothing under <data-dir>/plugins is launched, no remote
// plugin is contacted, and the admin API answers 503.
//
// ⚠ DEMO MODE FLIPS THE DEFAULT: with FILEX_DEMO_MODE on, plugins are off
// unless this variable explicitly says otherwise, because a demo hands an
// admin account to strangers and installing a plugin runs a program on the
// host. Set FILEX_PLUGINS_DISABLED=0 to override that deliberately.
//
// Otherwise ON by default,
// because a plugin is only ever installed by an admin — but an operator
// hardening a shared instance may not want the admin role to include
// "run a program on the server". See docs/PLUGINS.md.
PluginsDisabled bool `yaml:"plugins_disabled"`
// PluginConformance (FILEX_PLUGIN_CONFORMANCE) is enforce | warn | off.
//
// enforce (default): a plugin that fails a probe of a capability IT
// DECLARED is refused, and a storage cannot be saved on it. The reason a
// half-working plugin must not be usable is that the user cannot tell
// whose fault it is: they meet an upload button that fails and read it as
// filex being broken. warn registers it anyway and keeps the report (for
// somebody writing a plugin); off skips the probes.
PluginConformance string `yaml:"plugin_conformance"`
// PluginTrustedKeys (FILEX_PLUGIN_TRUSTED_KEYS, comma-separated) are
// ed25519 public keys, hex or base64. Set ANY key and filex refuses a
// plugin binary that is not signed by one of them.
//
// ⚠ The sha256 an install already records proves only that the file has
// not changed since it arrived — never that it came from somebody you
// trust. This is the setting that answers the second question, and until
// it is set nothing is asked.
PluginTrustedKeys []string `yaml:"plugin_trusted_keys"`
// PluginMaxInFlight (FILEX_PLUGIN_MAX_INFLIGHT) bounds concurrent
// operations per plugin. 0 keeps the default; a plugin at its ceiling
// refuses new work rather than queueing it, which is what stops one slow
// plugin from becoming one slow filex.
PluginMaxInFlight int `yaml:"plugin_max_in_flight"`
// AppPluginsDisabled (FILEX_APP_PLUGINS_DISABLED=1) turns the in-process
// WebAssembly app-plugin runtime off (internal/wasmplugin): nothing under
// <data-dir>/app-plugins is loaded, the user routes answer 404 and the
// admin routes 503. Demo mode flips the default to ON for the same
// reason storage plugins are off there: the demo's admin account is
// public, and an installed plugin runs code — sandboxed, but still code
// somebody else chose — for every visitor. Set the variable to 0 to
// override that deliberately. See docs/APP-PLUGINS.md.
AppPluginsDisabled bool `yaml:"app_plugins_disabled"`
// AppPluginMaxInputMB / AppPluginMaxOutputMB / AppPluginMaxWasmMB cap,
// per file, what a plugin job may read, what it may produce, and how big
// an installed module may be (FILEX_APP_PLUGIN_MAX_INPUT_MB etc.). Zero
// takes the defaults 256 / 512 / 64.
AppPluginMaxInputMB int `yaml:"app_plugin_max_input_mb"`
AppPluginMaxOutputMB int `yaml:"app_plugin_max_output_mb"`
AppPluginMaxWasmMB int `yaml:"app_plugin_max_wasm_mb"`
// SecretKey (FILEX_SECRET_KEY) encrypts the secrets filex has to be able to
// read back rather than merely compare — today the S3 access keys, because
// SigV4 derives an HMAC chain from the secret and so cannot work off a
// one-way hash. See internal/secretbox for what this does and does not buy.
//
// ⚠ Losing it makes every credential sealed under it unusable; they must be
// re-issued. It is not a password to rotate casually — treat it like the
// database, because losing one is as bad as losing the other.
SecretKey string `yaml:"secret_key"`
Log LogConfig `yaml:"log"`
DB DBConfig `yaml:"db"`
Auth AuthConfig `yaml:"auth"`
ExternalServices ExtServices `yaml:"external_services"`
Sync SyncConfig `yaml:"sync"`
Thumbs ThumbsConfig `yaml:"thumbs"`
Search SearchConfig `yaml:"search"`
CORS CORSConfig `yaml:"cors"`
Queue QueueConfig `yaml:"queue"`
Ops OpsConfig `yaml:"ops"`
Notify NotifyConfig `yaml:"notify"`
Demo DemoConfig `yaml:"demo"`
Sentry SentryConfig `yaml:"sentry"`
Seed SeedConfig `yaml:"seed"`
DAV DAVConfig `yaml:"dav"`
S3 S3Config `yaml:"s3"`
SFTP SFTPConfig `yaml:"sftp"`
FTPS FTPSConfig `yaml:"ftps"`
NFS NFSConfig `yaml:"nfs"`
Update UpdateConfig `yaml:"update"`
Upload UploadConfig `yaml:"upload"`
Cache CacheConfig `yaml:"cache"`
/* kimlik:e3 cloud */
Cloud CloudConfig `yaml:"cloud"`
// VersionsOnOverwrite installs the pre-write versioning guard. Default on.
// FILEX_VERSIONS_ON_OVERWRITE=0 turns it off -- the escape hatch for a
// deployment where a broken or full object store would otherwise refuse
// writes -- and =1 turns it back on, including over a config.yaml that set
// versions_on_overwrite: false (env wins; see applyEnv).
// NOTE: versions.keep_n=0 does NOT do this (0 means "unlimited"; the
// snapshot path falls back to DefaultRetention).
VersionsOnOverwrite bool `yaml:"versions_on_overwrite"`
// VersionsFailOpen lets a snapshot failure fall through to the write
// instead of refusing it. Default false -- Service.Snapshot's own contract
// is that a caller must NOT proceed past a failed snapshot. It exists
// because the fail-closed default has a sharp edge: if the object store
// fills up, snapshots start failing and EVERY overwrite on the instance is
// refused (desktop sync, WebDAV, OnlyOffice saves, the browser) and the
// only other lever is an env var plus a restart.
VersionsFailOpen bool `yaml:"versions_fail_open"`
}
Config is the top-level runtime configuration object.
type ConvertConfig ¶
type ConvertConfig struct {
URL string `yaml:"url"`
}
ConvertConfig — universal converter (p2r3/convert fork) embed URL.
type DAVConfig ¶
type DAVConfig struct {
Enabled bool `yaml:"enabled"`
}
DAVConfig — the WebDAV server surface at /dav (v0.3 "Bağlan" (Connect)). ON by default; FILEX_DAV=0 is the kill switch (the handler then answers 404).
type DemoConfig ¶
type DemoConfig struct {
// Mode flips the UI into the demo presentation. Backend itself
// stays a normal install — auth still happens against the local
// driver, the demo creds are just a regular user.
Mode bool `yaml:"mode"`
// User + Pass are the credentials the "Open the demo" CTA submits.
// Defaults: demo@demo.com / demo (operators must keep DB in sync).
User string `yaml:"user"`
Pass string `yaml:"pass"`
}
DemoConfig — public-demo affordances. When Mode=true the login page renders an "Open the demo" CTA that auto-submits the supplied credentials, plus a feature-tour card above the form.
type ExtServices ¶
type ExtServices struct {
OnlyOffice OnlyOfficeConfig `yaml:"onlyoffice"`
Drawio DrawioConfig `yaml:"drawio"`
Convert ConvertConfig `yaml:"convert"`
}
ExtServices — plug-and-play.
type FTPSConfig ¶
type FTPSConfig struct {
// Enabled — FILEX_FTPS. OFF by default: this one opens a control port AND
// a range of data ports.
Enabled bool `yaml:"enabled"`
// Addr is the control channel (2121 by convention; 21 needs root).
Addr string `yaml:"addr"`
// PublicHost is what passive-mode replies advertise.
//
// ⚠⚠ The setting FTP deployments get wrong, and it fails as a HANG rather
// than an error: the server answers PASV with an address the client cannot
// route to and the client waits until it times out. Behind NAT or in Docker
// it must be the address the CLIENT would use.
PublicHost string `yaml:"public_host"`
// PassivePortMin/Max bound the data ports. They must be open in the
// firewall and, under Docker, published one-for-one — a range open on the
// server and closed at the edge is the same hang.
PassivePortMin int `yaml:"passive_port_min"`
PassivePortMax int `yaml:"passive_port_max"`
// CertFile/KeyFile are the TLS material. Empty generates a self-signed pair
// into the data dir — encrypted but unverified, and the guide says so.
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
// Banner is the greeting line.
Banner string `yaml:"banner"`
// IdleTimeout in seconds; 0 uses the package default.
IdleTimeout int `yaml:"idle_timeout"`
}
FTPSConfig controls the FTPS endpoint (internal/ftpsrv).
⚠⚠ There is no "plain FTP" switch and there will not be one. Plain FTP sends the password in the clear and the file after it; a flag that turned TLS off would be a flag that publishes a user's credentials to anything on the path.
type HeaderProxyConfig ¶
type HeaderProxyConfig struct {
EmailHeader string `yaml:"email_header"`
GroupHeader string `yaml:"group_header"`
TrustedIPs []string `yaml:"trusted_ips"`
AdminGroup string `yaml:"admin_group"`
// Provider is the tenant SLUG a just-in-time account is homed in when the
// request Host maps to no tenant. See LDAPConfig.Provider — same rule, and
// on this driver the Host is almost always there, so it is rarely needed.
Provider string `yaml:"provider"`
}
HeaderProxyConfig — accept Cloudflare Access / Authelia headers.
type LDAPConfig ¶
type LDAPConfig struct {
URL string `yaml:"url"`
BindDN string `yaml:"bind_dn"`
BindPassword string `yaml:"bind_password"`
BaseDN string `yaml:"base_dn"`
UserFilter string `yaml:"user_filter"`
EmailAttr string `yaml:"email_attr"`
StartTLS bool `yaml:"start_tls"`
// CAFile is a PEM bundle holding the CA that signed the directory's
// certificate. Empty verifies against the system trust store, which is what
// the driver always did — and what forced installs with a private/internal
// CA to rebuild the container's /etc/ssl/certs/ca-certificates.crt just to
// reach their own AD. Appended to the system pool, not substituted for it.
CAFile string `yaml:"ca_file"`
// ProtocolLogin lets directory accounts authenticate over the non-HTTP
// protocols (WebDAV, SFTP, FTPS, S3, NFS) with their directory password.
// ON by default: with it off, an account that can sign in to the web UI is
// answered 401 everywhere else, which is indistinguishable from a wrong
// password. Turn it off to keep the directory password on the login form
// only and require an API token everywhere else.
//
// ⚠ Accounts with TOTP enabled are refused on those protocols regardless,
// exactly as local passwords are — none of them has a second-factor
// channel. See internal/protocolauth.
ProtocolLogin bool `yaml:"protocol_login"`
// Provider is the tenant SLUG a just-in-time directory account is homed in
// when the login carries no Host that maps to one — i.e. the protocol
// logins (SFTP, FTPS, NFS), which present a password on a socket.
//
// ⚠ Multi-tenant installs only, and only for ACCOUNT CREATION. Empty means
// "refuse to create one", which is the safe default: the alternative
// fallback is `default`, and `default` is the confine-exempt supertenant.
// An account that already exists signs in over every protocol either way.
Provider string `yaml:"provider"`
}
LDAPConfig — directory bind.
type LogConfig ¶
type LogConfig struct {
Level string `yaml:"level"` // debug, info, warn, error
Format string `yaml:"format"` // text, json
}
LogConfig — slog level + format.
type NFSConfig ¶
type NFSConfig struct {
// Enabled — FILEX_NFS. OFF by default, and more emphatically than the
// others: switching it on is a decision about the network it sits on.
Enabled bool `yaml:"enabled"`
// Addr is the listen address. 2049 is the registered port and what clients
// assume; anything else needs `-o port=` on every mount.
Addr string `yaml:"addr"`
}
NFSConfig controls the NFSv3 endpoint (internal/nfssrv).
⚠⚠ NFSv3 is unencrypted and unauthenticated on the wire. filex binds identity to the EXPORT PATH (32 bytes of entropy, see model.NFSExport) rather than trusting the uid a client asserts — but the traffic itself is still readable by anything on the path. This is the NAS-on-the-LAN protocol; `filex mount` (FUSE over HTTPS) is the answer for anything off-LAN.
type NotifyConfig ¶
type NotifyConfig struct {
// Enabled toggles the entire subsystem. When false the API returns
// 503 from /api/notifications/... and Service.Send is a no-op.
Enabled bool `yaml:"enabled"`
// WebhookURL receives a generic JSON POST per event.
WebhookURL string `yaml:"webhook_url"`
// WebhookToken — optional Authorization: Bearer <token>.
WebhookToken string `yaml:"webhook_token"`
}
NotifyConfig — webhook + in-app channel configuration. Both are optional; leaving WebhookURL empty disables outbound delivery while the in-app bell continues to record events.
type OIDCConfig ¶
type OIDCConfig struct {
Issuer string `yaml:"issuer"`
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
RedirectURL string `yaml:"redirect_url"`
RoleClaim string `yaml:"role_claim"`
AdminGroup string `yaml:"admin_group"`
// AutoRedirect makes the login page start the OIDC flow immediately
// (SSO-first installs). The password form stays reachable via ?local=1
// for break-glass/admin logins. OFF by default — unchanged behavior.
AutoRedirect bool `yaml:"auto_redirect"`
// Logout picks what signing out of an OIDC session ends (FILEX_OIDC_LOGOUT):
// "idp" (default) — filex's session AND the IdP's, when the IdP
// advertises an end_session_endpoint (RP-initiated
// logout; the IdP must allow the post-logout redirect,
// docs/SSO.md);
// "local" — filex's session only; the person stays signed in at
// the IdP (the behavior before this option existed).
// Anything else means the default.
Logout string `yaml:"logout"`
}
OIDCConfig — Keycloak/Auth0/etc.
func (OIDCConfig) LocalLogout ¶
func (o OIDCConfig) LocalLogout() bool
LocalLogout reports whether signing out leaves the IdP's session alone.
type OnlyOfficeConfig ¶
type OnlyOfficeConfig struct {
URL string `yaml:"url"`
JWTSecret string `yaml:"jwt_secret"`
// CallbackURL is the address the DOCUMENT SERVER uses to reach filex for
// the document bytes and the save. Empty means "the public URL", which is
// right wherever one address serves both the browser and the container.
//
// ⚠ It is not always the same address. FILEX_PUBLIC_URL also builds every
// share link a person receives, so an install whose document server cannot
// resolve the public hostname had no way to express the difference and its
// saves were silently lost (issue #17).
CallbackURL string `yaml:"callback_url"`
}
OnlyOfficeConfig — Document Server URL + JWT secret.
type OpsConfig ¶
type OpsConfig struct {
// DeleteWorkers is how many items of ONE delete job are put in the trash
// at the same time. FILEX_OPS_DELETE_WORKERS, default 4; anything below 1
// means the default.
//
// Jobs still run one after another, in the order they were queued — only
// the items inside a delete job overlap. On an object store every trashed
// file is several round trips, so a large delete is almost all waiting,
// and one item at a time made a delete of tens of thousands of files run
// for hours while every other queued job waited behind it.
DeleteWorkers int `yaml:"delete_workers"`
}
OpsConfig — the copy/move/delete queue (internal/ops).
type QueueConfig ¶
type QueueConfig struct {
// Driver selects the queue backend: sqlite | postgres | redis.
// Empty follows the DATABASE driver (sqlite→sqlite, postgres→postgres);
// on MySQL there is no shared-database driver, so empty means "no
// persistent queue" until an operator configures redis.
Driver string `yaml:"driver"`
// DSN is the connection string for postgres ("postgres://...") or
// redis ("redis://..."). For sqlite the application DB handle is
// shared automatically and DSN is ignored.
DSN string `yaml:"dsn"`
// Workers controls Pool size. <=0 → 4.
Workers int `yaml:"workers"`
// Enabled lets operators turn the persistent queue off entirely
// (the legacy ops.Service still handles copy/move/delete in that
// case). Default: true.
Enabled bool `yaml:"enabled"`
}
QueueConfig — persistent op queue. Driver "sqlite" (default) shares the application DB; "postgres" / "redis" can be wired for production or HA setups (see internal/queue/drivers/{postgres,redis}).
type S3Config ¶
type S3Config struct {
// Enabled — FILEX_S3 kill switch. ON by default like /dav: the endpoint
// refuses every unsigned request anyway, and an access key has to be
// minted before anything can reach it.
Enabled bool `yaml:"enabled"`
// Domain enables virtual-hosted-style addressing (bucket.s3.example.com).
// Empty leaves path-style only, which is what restic and the older SDKs
// use — so an install without a wildcard DNS record still works, it just
// needs `path_style` in the client config.
//
// ⚠ Setting it requires a wildcard A record AND a wildcard certificate for
// *.<domain>; without both, current SDKs (which default to virtual-hosted)
// fail at TLS rather than with anything that names the cause.
Domain string `yaml:"domain"`
}
S3Config controls the S3-compatible endpoint (internal/s3api).
type SFTPConfig ¶
type SFTPConfig struct {
// Enabled — FILEX_SFTP. OFF by default, unlike /dav and S3: this surface
// opens a TCP port of its own, and a port nobody asked for is not something
// to switch on for them.
Enabled bool `yaml:"enabled"`
// Addr is the listen address. 2022 by convention — sftpgo and
// `rclone serve sftp` both use it, while 2222 means "SSH in a container".
Addr string `yaml:"addr"`
// HostKeyDir holds the server's host keys.
//
// ⚠ It must survive a rebuild. Regenerating host keys gives every user
// REMOTE HOST IDENTIFICATION HAS CHANGED — indistinguishable from an attack,
// and usually "fixed" by deleting the known_hosts line, which trains people
// to ignore the one warning that matters. Empty puts them in the data dir.
HostKeyDir string `yaml:"host_key_dir"`
// Banner is shown before authentication. Empty sends none.
Banner string `yaml:"banner"`
// MaxSpool caps one upload's spool file. 0 uses the package default.
MaxSpool int64 `yaml:"max_spool"`
}
SFTPConfig controls the SFTP endpoint (internal/sftpsrv).
type SearchConfig ¶
type SearchConfig struct {
Enabled bool `yaml:"enabled"`
IndexPath string `yaml:"index_path"`
// Content toggles async file-content extraction into the index ("Bul"
// wave). ON by default; FILEX_SEARCH_CONTENT=0 is the kill-switch.
Content bool `yaml:"content"`
// ContentMaxBytes caps the SOURCE file size eligible for extraction
// (FILEX_SEARCH_CONTENT_MAX). <=0 falls back to 5 MiB. The extracted
// text itself is always capped at 200 KiB.
ContentMaxBytes int64 `yaml:"content_max_bytes"`
// AutoRebuild lets filex repair an index written by an older document
// schema, in the background, at startup. ON by default;
// FILEX_SEARCH_AUTO_REBUILD=0 is the kill-switch.
//
// It is on by default because the alternative shipped once and did not
// work: v0.29.0 improved filename matching for everyone EXCEPT the
// installations that already had an index, told them so in an admin
// endpoint nobody reads, and the issue reporter upgraded and correctly
// said nothing had changed.
AutoRebuild bool `yaml:"auto_rebuild"`
}
SearchConfig — bleve index.
type SeedConfig ¶
type SeedConfig struct {
AdminEmail string `yaml:"admin_email"`
AdminPassword string `yaml:"admin_password"`
SiteName string `yaml:"site_name"`
TrashDays string `yaml:"trash_retention_days"`
// ShareMaxTTLDays seeds the `share.max_ttl_days` setting — the longest
// life a NEW share link may be given (FILEX_SHARE_MAX_TTL, e.g. "7" or
// "30d"; "0" = unlimited). Like the other seeds it only applies when the
// setting has never been written; after that the admin UI owns it.
SMTP SeedSMTP `yaml:"smtp"`
Storage SeedStorage `yaml:"storage"`
}
SeedConfig holds one-time bootstrap values applied to the DB on first boot, only when the target record is ABSENT (operator UI edits are never clobbered). It lets a fresh `helm install` / `docker compose up` come up fully configured from env alone — admin user, SMTP, branding, trash policy and an initial storage — with zero admin-UI clicks. Consumed by internal/server/seed.go. (Auth/OIDC is env-authoritative already via AuthConfig, so it is not duplicated here.)
type SeedSMTP ¶
type SeedSMTP struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
Username string `yaml:"username"`
Password string `yaml:"password"`
From string `yaml:"from"`
TLS string `yaml:"tls"` // starttls | tls | none
}
SeedSMTP mirrors the mailer's smtp.* settings keys.
func (SeedSMTP) Configured ¶
Configured reports whether enough SMTP fields are set to seed a row.
type SeedStorage ¶
type SeedStorage struct {
Driver string `yaml:"driver"` // local | s3 | sftp | webdav | ftp | "" (none)
Name string `yaml:"name"`
MountPath string `yaml:"mount_path"`
// Config is a raw JSON object used verbatim as the storage's driver config.
// Set it for sftp/webdav/ftp (or advanced s3); overrides the fields below.
Config string `yaml:"config"`
Path string `yaml:"path"` // local driver on-disk root
// s3 driver:
Bucket string `yaml:"bucket"`
Prefix string `yaml:"prefix"`
Endpoint string `yaml:"endpoint"`
Region string `yaml:"region"`
AccessKey string `yaml:"access_key"`
SecretKey string `yaml:"secret_key"`
PathStyle bool `yaml:"path_style"`
}
SeedStorage describes an initial storage row to create when no storage exists yet. Driver "" (default) seeds nothing.
For local + s3 the ergonomic fields below are enough. To seed ANY other driver (sftp, webdav, ftp) — i.e. connect an EXISTING external storage — set Driver plus Config to the driver's raw config JSON; it is used verbatim.
type SentryConfig ¶
SentryConfig — optional Sentry-wire error reporting (self-hosted GlitchTip at errors.example.com). An empty DSN disables it entirely (default build reports nothing). Environment tags events (e.g. production / demo) so one project can serve multiple deployments.
type SyncConfig ¶
type SyncConfig struct {
// DefaultInterval is the poll cadence for storages with no
// sync_interval_s of their own. FILEX_SYNC_INTERVAL.
DefaultInterval time.Duration `yaml:"default_interval"`
}
SyncConfig — storage sync settings.
⚠ There is deliberately no `Workers` here any more. FILEX_SYNC_WORKERS was parsed into a field that nothing read, while CONFIGURATION.md advertised it as "concurrent storage sync workers" — there is no pool to size: the sync worker runs one goroutine per enabled storage (internal/sync.Worker.startOne) and always has. Inventing a pool to justify the variable would be a redesign; documenting a knob that does nothing is worse than either, so the knob is gone and the doc says what actually happens.
type ThumbsConfig ¶
type ThumbsConfig struct {
Enabled bool `yaml:"enabled"`
Formats []string `yaml:"formats"`
CacheDir string `yaml:"cache_dir"`
// SweepInterval is how often the cached JPEGs are reconciled against the
// node catalogue, so a file whose node no longer exists stops occupying
// disk (FILEX_THUMBS_SWEEP_INTERVAL, default 6h, 0 = never).
//
// ⚠ The sweeper is deliberately independent of Enabled: an operator who
// turns thumbnails OFF still has whatever the cache accumulated while they
// were on, and that is exactly when nobody is watching it.
SweepInterval time.Duration `yaml:"sweep_interval"`
// URLTTL is how long a stamped `thumb_url` stays valid
// (FILEX_THUMBS_URL_TTL, default 24h).
//
// The stamp is what lets a bare <img src> fetch a preview with no header
// and no cookie -- see internal/thumb/sign.go. Shortening it narrows the
// window in which a leaked URL still resolves; it never locks out the SPA,
// the desktop app or an embedded explorer, all of which fetch thumbnails
// with credentials and are authorized per request.
//
// ⚠ 0 means "use the default", not "never expires": an unbounded stamp
// would be a permanent bearer capability for that node's preview.
URLTTL time.Duration `yaml:"url_ttl"`
}
ThumbsConfig — generation policy.
type UpdateConfig ¶
type UpdateConfig struct {
// Enabled controls the periodic check. False = no outbound request at all.
Enabled bool `yaml:"enabled"`
// Policy: off | manual | patch | minor. Which part of x.y.z may be applied
// without asking. "patch" is what AUTO_UPGRADE=true selects.
Policy string `yaml:"policy"`
// Channel selects the manifest flavor ("stable").
Channel string `yaml:"channel"`
// ManifestURL overrides the default release index (mirrors, forks,
// air-gapped installs that publish their own).
ManifestURL string `yaml:"manifest_url"`
// Window is a daily maintenance window for automatic upgrades,
// "03:00-05:00" in the server's local time. Empty = any time.
Window string `yaml:"window"`
// Interval between checks. Zero → 24h; anything under an hour is raised to
// an hour (a self-hosted install has no reason to poll harder).
Interval time.Duration `yaml:"interval"`
}
UpdateConfig — release awareness and (where the install owns its binary) self-upgrade. See docs/UPDATES.md.
The default is "check and tell me, change nothing": Enabled=true with Policy="manual". Nothing moves on its own until the operator opts in with AUTO_UPGRADE=true (= policy "patch"). Checking can be turned off entirely with FILEX_UPDATE_CHECK=0, which stops all outbound requests.
type UploadConfig ¶
type UploadConfig struct {
// StagingDir is where in-flight upload parts live. Defaults to
// <data_dir>/uploads. Must be on a filesystem with room for the largest
// upload you expect — the whole object passes through it.
StagingDir string `yaml:"staging_dir"`
// ChunkSize is the part size handed to clients that do not ask for one.
// Clients may request a different size; the server's answer is binding.
ChunkSize int64 `yaml:"chunk_size"`
// StagingTTL is how long a staging directory may sit with no activity
// before the sweeper removes it. FILEX_UPLOAD_STAGING_TTL.
StagingTTL time.Duration `yaml:"staging_ttl"`
// SweepInterval is how often the sweeper runs.
SweepInterval time.Duration `yaml:"sweep_interval"`
}
UploadConfig — staged (resumable, driver-agnostic) uploads. See docs/UPLOADS.md.