| 1 | This file contains details about the configuration files. |
| 2 | |
| 3 | ### Where is it stored |
| 4 | |
| 5 | Configuration is stored in the file `config.yaml`, exception made for custom HTML which is stored in `custom.html`. |
| 6 | |
| 7 | These files are kept in the same folder of `hfs.exe` if you are using this kind of distribution on Windows, |
| 8 | or `$HOME/.hfs` on other systems, where *$HOME* varies with the system and is the user's home folder. |
| 9 | Anyway, the current working directory (CWD) is printed by HFS in the first lines of the console. |
| 10 | |
| 11 | Many things are stored in the CWD, like the plugins you install. |
| 12 | You can decide a different CWD passing `--cwd SOME_FOLDER` parameter at command line. |
| 13 | |
| 14 | If you are not sure what your `cwd` is, look in the console, and you'll see that in first lines of your console. |
| 15 | Here is an example, look at the 6th line: |
| 16 | ``` |
| 17 | HFS ~ HTTP File Server |
| 18 | © Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt |
| 19 | started 2026-01-03 10:10:00 |
| 20 | version 3.0.0 |
| 21 | build 2025-12-20T13:20:50.027Z |
| 22 | working directory (cwd) /Users/rejetto/.hfs |
| 23 | node v20.19.6 |
| 24 | platform darwin arm64 binary |
| 25 | ``` |
| 26 | |
| 27 | ### How to modify configuration |
| 28 | |
| 29 | Configuration can be done in several ways |
| 30 | - accessing the Admin-panel with your browser |
| 31 | - it will automatically open when you start HFS. Bookmark it. |
| 32 | If your port is 8000 the address will be http://localhost:8000/~/admin |
| 33 | - directly editing the `config.yaml` file. As soon as you save, it is reloaded and changes are applied |
| 34 | - if you don't want to use an editor, consider typing this (example) command inside the folder where the config file is: |
| 35 | `echo "port: 1080" >> config.yaml` |
| 36 | - passing via command line at start in the form `--NAME VALUE`. Values can use JSON syntax. |
| 37 | - using envs in the form `HFS_<uppercase property name>`, like `HFS_PORT=80` if you want to change the config `port`, |
| 38 | but the same applies to any other config available. Values can use JSON syntax. |
| 39 | - after HFS has started you can enter console command in the form `config NAME VALUE` |
| 40 | - setting special env `HFS_ENV_BOOTSTRAP=true` will disable other envs when file config.yaml already exists. |
| 41 | - env `DISABLE_UPDATE` (designed for containers) will disable updating, but check-for-update will still be possible. |
| 42 | |
| 43 | `NAME` stands for the property name that you want to change. See the complete list below. |
| 44 | |
| 45 | ### Configuration properties |
| 46 | |
| 47 | Some properties use a `Who` descriptor, with one of these values: |
| 48 | - `true`: anyone can, even people who didn't log in. |
| 49 | - `false`: no one can. |
| 50 | - `"*"`: any account can, i.e. anyone who logged in. |
| 51 | - `"admin"`: any account with admin-panel access. |
| 52 | - `[ frank, peter ]`: the list of accounts who can. |
| 53 | |
| 54 | - `port` where to accept http connections. Default is 80. |
| 55 | - `vfs` the files and folders you want to expose. For details see the dedicated following section. |
| 56 | - `log` path of the log file. Default is `access.log`. |
| 57 | - `log_rotation` frequency of log rotation. Accepted values are `daily`, `weekly`, `monthly`, or empty string to disable. Default is `weekly`. |
| 58 | - `log_api` should api calls be logged? Default is `true`. |
| 59 | - `log_gui` should GUI files be logged? Default is `false`. |
| 60 | - `log_spam` log *failed* requests that are considered spam. Default is false. |
| 61 | - `log_ua` include user-agent in the logs. Default is false. |
| 62 | - `track_ips` keep track of all IP addresses seen. Default is true. |
| 63 | - `error_log` path of the log file for errors. Default is `error.log`. |
| 64 | - `dont_log_net` don't include in log entries if IP matches this network mask. Default is `127.0.0.1|::1`. |
| 65 | - `accounts` list of accounts. For details see the dedicated following section. |
| 66 | - `mime` most types are already detected automatically, but you can override them. E.g.: `"*.jpg": image/jpeg` |
| 67 | You can specify multiple entries, or separate multiple file masks with a p|pe. |
| 68 | You can use the special value `auto` to attempt automatic detection. |
| 69 | - `max_kbps` throttle output speed. Default is Infinity. |
| 70 | - `max_kbps_per_ip` throttle output speed on a per-ip basis. Default is Infinity. |
| 71 | - `zip_calculate_size_for_seconds` how long should we wait before the zip archive starts streaming, trying to understand its finale size. Default is 1. |
| 72 | - `open_browser_at_start` should HFS open browser on localhost on start? Default is true. |
| 73 | - `https_port` listen on a specific port. Default is -1 (disabled). |
| 74 | - `cert` use this file for https certificate. Minimum to start https is to give a cert and a private_key. Default is none. |
| 75 | - `private_key` use this file for https private key. Default is none. |
| 76 | - `allowed_referer` you can decide what domains can link to your files. Wildcards supported. Default is any. |
| 77 | - `block` a list of rules that will block connections. E.g.: |
| 78 | ``` |
| 79 | block: |
| 80 | - ip: 192.168.0.90 |
| 81 | ``` |
| 82 | [Syntax supports wildcards and more.](https://github.com/rejetto/hfs/wiki/Wildcards#network-masks) |
| 83 | - `plugins_config` this is a generic place where you can find/put configuration for each plugin, at least those that need configuration. |
| 84 | - `enable_plugins` if a plugin is not present in this list, it won't run. Defaults is `[ antibrute ]`. |
| 85 | - `localhost_admin` should Admin be accessed without credentials when on localhost. Default is true. |
| 86 | - `proxies` number of proxies between server and clients to be trusted about providing clients' IP addresses. Default is 0. |
| 87 | - `delete_unfinished_uploads_after` should unfinished uploads be deleted after a number of seconds. 0 for immediate, empty for never. Default is 1 day. |
| 88 | - `favicon` path to file to be used as favicon. Default is none. |
| 89 | - `force_https` redirect http traffic to https. Requires https to be working. Default is true. |
| 90 | - `force_lang` force translation for frontend. Default is none, meaning *let browser decide*. |
| 91 | - `admin_net` net-mask specifying what addresses are allowed to access Admin-panel. Default is any. |
| 92 | - `title` text displayed in the tab of your browser. Default is "File server". |
| 93 | - `file_menu_on_link` if to display file-menu when clicking on a link, or have a dedicated button instead. Default is true. |
| 94 | - `min_available_mb` refuse to accept uploads if available disk space is below this threshold. Default is 100. |
| 95 | - `dont_overwrite_uploading` uploading a file with name already present in the folder will have a number appended in the name if this is enabled. |
| 96 | Default is true. Affects the frontend only, but you can get the same effect using the `?existing=rename` in the url. |
| 97 | - `keep_session_alive` keeps you logged in while the page is left open and the computer is on. Default is true. |
| 98 | - `session_duration` after how many seconds should the login session expire. Default is a day. |
| 99 | - `force_webdav_login` force WebDAV clients to authenticate. Accepts: `false` (disabled), `true` (all user-agents), or a case-insensitive regex string (only matching user-agents). Default is true. |
| 100 | - `webdav_initial_auth` one-time login prompt for matching WebDAV user-agents (used only when `force_webdav_login` does not match). Accepts: `false` (disabled), `true` (all user-agents), or a case-insensitive regex string. Default is `WebDAVFS`. |
| 101 | - `acme_domain` domain used for ACME certificate generation. Default is none. |
| 102 | - `acme_renew` automatically renew acme certificate close to expiration. Default is false. |
| 103 | - `listen_interface` network interface to listen on, by specifying IP address. Default is any. |
| 104 | - `base_url` URL to be used for links generation. Default is automatic. |
| 105 | - `force_address` disconnect any request not made with one of the hosts specified in `roots` or `base_url`. Default is false. |
| 106 | - `ignore_proxies` stop warning about detected proxies. Default is false. |
| 107 | - `comments_storage` choose where to read/write comments. Default is in file `descript.ion`. |
| 108 | - You can set `attr` to use only file's attributes, or `attr+ion` to store in file's attributes but fall-back to `descript.ion` as read-only.` |
| 109 | - `descript_ion_encoding` text encoding to be used for file `descript.ion`. [List of supported values](https://github.com/ashtuchkin/iconv-lite/wiki/Supported-Encodings). Default is `utf8`. |
| 110 | - `server_code` javascript code that works similarly to [a plugin](dev-plugins.md). |
| 111 | - `tiles_size` starting value for frontend's tile size. Default is 0. |
| 112 | - `auto_play_seconds` starting value for frontend's auto_play_seconds (used in Show). Default is 5. |
| 113 | - `theme` starting value for theme. Default is "auto". |
| 114 | - `sort_by` starting value for sort-by. Values can be: name, extension, size, time. Default is "name". |
| 115 | - `sort_numerics` starting value for sort-numeric-names. Default is false. |
| 116 | - `folders_first` starting value for sort-folders-first. Default is true. |
| 117 | - `invert_order` starting value for invert-order. Default is false. |
| 118 | - `show_uploader` who can see who uploaded files. Value is a `Who` descriptor. Default is `"admin"`. |
| 119 | - `update_to_beta` includes beta versions searching for updates. Default is false. |
| 120 | - `roots` maps hosts (or mask of hosts) to a root different from the home folder. Default is none. E.g. |
| 121 | ``` |
| 122 | roots: |
| 123 | music.domain.com: /music |
| 124 | image.domain.com: /image |
| 125 | ``` |
| 126 | - `max_downloads` limit the number of concurrent downloads on the whole server. Default is unlimited. |
| 127 | - `max_downloads_per_ip` limit the number of concurrent downloads for the same IP address. Default is unlimited. |
| 128 | - `max_downloads_per_account` limit the number of concurrent downloads for each account. This is enforced only for connections that are logged in and will override other similar settings. Default is unlimited. |
| 129 | - `geo_enable` when enabled, country is determined for each request/connection. The necessary database will be downloaded every month (2MB). |
| 130 | - `geo_allow` set true if `geo_list` should be treated as whitelist, set false for blacklist. Default will ignore the list. |
| 131 | - `geo_list` list of country codes to be used as whitelist or blacklist. Default is none. |
| 132 | - `geo_allow_unknown` set false to disconnect connections for which country cannot be determined. Works only if `geo_allow` is set. Default is true. |
| 133 | - `dynamic_dns_url` URL to be requested to keep a domain updated with your latest IP address. |
| 134 | Optionally, you can append “>” followed by a regular expression to determine a successful answer; otherwise status code will be used. |
| 135 | Multiple URLs are supported, and you can specify one for each line. |
| 136 | - `outbound_proxy` if you need outgoing http(s) requests to pass through an HTTP proxy. E.g.: `http://user:password@localhost:8888`. Default is none. |
| 137 | Setting one will trigger a test request to google.com. You can skip this with env HFS_SKIP_PROXY_TEST=1 . |
| 138 | - `auto_basic` automatically detect (based on user-agent) when the basic web interface should be served, to support legacy browsers. Default is true. No UI. |
| 139 | You can disable it setting it to `false`, or recognize additional user-agents by setting a regular expression. |
| 140 | - `file_timeout` number of seconds to wait before giving up when accessing a file. Default is 3. No UI. |
| 141 | - `smart_unc_folder_detection` Windows-only optimization for UNC paths in VFS. When enabled, if the name of the element has no dot, it is assumed to be a folder without doing a stat call. |
| 142 | This is faster with unreachable SMB shares, but heuristic and not fully reliable. Disable to always use regular detection. Default is true. No UI. |
| 143 | - `authorization_header` enable support for the HTTP `Authorization` header. Default is true. No UI. |
| 144 | - `cache_control_disk_files` number of seconds after which the browser should bypass the cache and check the server for an updated version of the file. Default is 5. No UI. |
| 145 | - `disable_custom_html` disable the content of `custom_html`. Default is false. |
| 146 | - `split_uploads` The size in megabytes of the chunks the upload will be split into. Default is none. |
| 147 | - `create-admin` special entry to quickly create an admin account. The value will be set as the password. As soon as the account is created, this entry is removed. |
| 148 | |
| 149 | #### Virtual File System (VFS) |
| 150 | |
| 151 | The virtual file system is a tree of files and folders, collectively called *nodes*. |
| 152 | By default, a node is a folder, unless you provide for it a source that's a file. |
| 153 | The `vfs` config is a single root node. You can either bind a disk path directly to the root, like so |
| 154 | ``` |
| 155 | vfs: |
| 156 | source: /data |
| 157 | ``` |
| 158 | or expose paths as children of the root: |
| 159 | ``` |
| 160 | vfs: |
| 161 | children: |
| 162 | - source: /data |
| 163 | ``` |
| 164 | In the first example, the root of HFS shows the contents of `/data`. |
| 165 | In the second example, HFS shows a folder named "data" at the root (name inferred from the path). |
| 166 | |
| 167 | Valid keys in a node are: |
| 168 | - `name`: this is the name we'll use to display this file/folder. If not provided, HFS will infer it from the source. At least `name` or `source` must be provided. |
| 169 | - `source`: absolute or relative path of where to get the content |
| 170 | - `children`: just for folders, specify its virtual children. |
| 171 | Value is a list and its entries are nodes. |
| 172 | - `rename`: when `source` is a folder, you can rename entries *virtually* as they are read from disk. |
| 173 | Value is a map "original name" → "new name". No UI. |
| 174 | - `mime`: specify what mime to use for this resource. Use "auto" for automatic detection. |
| 175 | - `url`: when this value is present, the element is a link to the URL you specify. |
| 176 | - `order`: a number that you can set if you want to force the position of this element to the top or the bottom of the list. |
| 177 | A positive number for the top, negative for the bottom. If you set "1" for an entry and "2" for another, the "2" will be the topmost. |
| 178 | - `target`: optional, for links only, used to [open the link in a new browser](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target). E.g. `_blank` |
| 179 | - `accept`: valid only on upload folders; not enforced, just hinting the browser. E.g. `.zip,.rar` |
| 180 | - `default`: use this with a folder where you want to serve a file, instead of the standard page with the list of files. |
| 181 | The value must be the name of the file to serve. E.g.: `index.html`. |
| 182 | The value must be an absolute or relative path in the VFS, not a path on the disk. It works also with other types of files. |
| 183 | Using this will make `mime` default to "auto". |
| 184 | - `can_read`: specify who can download this entry. Value is a `Who` descriptor, or a VFS-specific extension. Default is `true`. |
| 185 | |
| 186 | VFS permissions also accept these extra forms: |
| 187 | - `can_SOMETHING`: copy the permission from another permission. This is convenient to have the same value for different permissions. E.g. `can_see` |
| 188 | - `{ this?: ..., children?: ... }`: this form is useful only for folders. Each value uses the same permission descriptor. By using it, you can have |
| 189 | different permissions for the folder itself and its children. For example, having only the `this` property |
| 190 | will make the permission limited to the folder and not be inherited by children. Otherwise, having only |
| 191 | the `children` will make the permission have no effect on the folder but only on its content. |
| 192 | - `this` specifies permission for this folder |
| 193 | - `children` specifies permission for the content. |
| 194 | - `can_see`: specify who can see this element. Even if a user can download, you can still make the file not appear in the list. |
| 195 | Value uses the same permission descriptor described above. Default is `can_read`. |
| 196 | - `can_upload`: specify who can upload. Applies to folders with a source. Default is `"admin"`. |
| 197 | - `can_list`: specify who can see the content of a folder. Default is `can_read`. |
| 198 | - `can_archive`: specify who can get the zip a folder or a set of files. Default is `can_read`. |
| 199 | - `can_delete`: specify who can delete. Applies to folders with a source. Default is `"admin"`. |
| 200 | - `masks`: maps a file mask to a set of properties as the one documented in this section. E.g. |
| 201 | ``` |
| 202 | myfile.txt: |
| 203 | can_see: false |
| 204 | can_read: false |
| 205 | "**/*.mp3": |
| 206 | can_read: false |
| 207 | "*.jpg|*.png": |
| 208 | mime: auto |
| 209 | ``` |
| 210 | Rules on top have priority over bottom rules. Inner rules have priority over parent's rules. |
| 211 | A mask can carry any node property (even property "masks" itself). |
| 212 | If the mask ends with `|files|`, then it will match only files and not folders. |
| 213 | You can get the opposite effect with suffix `|folders|`. |
| 214 | |
| 215 | Permissions set on an inner element will override inherited permissions. |
| 216 | This means that you can restrict access to folder1 and yet decide to give free access to folder1/subfolder2. |
| 217 | |
| 218 | #### Accounts |
| 219 | |
| 220 | All accounts go under `accounts:` property, as a dictionary where the key is the username. |
| 221 | E.g. |
| 222 | ``` |
| 223 | accounts: |
| 224 | admin: |
| 225 | password: hello123 |
| 226 | admin: true |
| 227 | frank: |
| 228 | password: another |
| 229 | belongs: group1 |
| 230 | guest: |
| 231 | password: guest |
| 232 | group1: |
| 233 | ``` |
| 234 | |
| 235 | As soon as the config is read, HFS will encrypt passwords (if necessary) in a non-reversible way. It means that `password` property is replaced with an encrypted property: `srp`. |
| 236 | |
| 237 | As you can see in the example, `group1` has no password. This implies that you cannot log in as `group1`, but still `group1` exists and its purpose is to |
| 238 | gather multiple accounts and refer to them collectively as `group1`, so you can quickly share powers among several accounts. |
| 239 | |
| 240 | For each account entry, this is the list of properties you can have: |
| 241 | |
| 242 | - `ignore_limits` to ignore speed limits. Default is `false`. |
| 243 | - `redirect` provide a URL if you want the user to be redirected upon login. Default is none. |
| 244 | - `admin` set `true` if you want to let this account log in to the Admin-panel. Default is `false`. |
| 245 | - `belongs` an array of usernames of other accounts from which to inherit their permissions. Default is none. |
| 246 | - `password` a temporary unencrypted password, transformed into `srp` ASAP (and removed). |
| 247 | - `srp` encrypted password. Don't modify this, HFS will create it from `password` field. |
| 248 | - `disabled` prevents using this account. Default is false. |
| 249 | If a user is disabled, it cannot log in. A user won't inherit permissions from a group if the group is disabled. |
| 250 | If all of its groups are disabled, then it cannot log in, even if the user itself is not disabled. |
| 251 | - `expire` account won't work once the time has passed this timestamp. Use JSON timestamp syntax. Default is none. |
| 252 | - `days_to_live` used to set `expire` on first login. Default is none. |
| 253 | - `disable_password_change` set `true` if you want to forbid password change for this user. Default is `false`. |
| 254 | - `require_password_change` set `true` if you want to require password change for this user. Default is `false`. |
| 255 | - `allow_net` a mask of addresses to restrict the access of the account |
| 256 | |
| 257 | ### Specify another file |
| 258 | |
| 259 | Do you need to load a different config file that's not `config.yaml`? |
| 260 | Use this parameter at command line `--config PATH` or similarly with an env `HFS_CONFIG`. |
| 261 | The path you specify can be either a folder or full-path to the file. |