agate

Simple gemini server for static files
git clone https://github.com/mbrubeck/agate.git
Log | Files | Refs | README

index.gmi (28701B)


      1 # Agate
      2 
      3 ## Simple Gemini server for static files
      4 
      5 Agate is a server for the Gemini network protocol, built with the Rust programming language. Agate has very few features, and can only serve static files. It uses async I/O, and should be quite efficient even when running on low-end hardware and serving many concurrent requests.
      6 
      7 Since Agate by default uses port 1965, you should be able to run other servers (like e.g. Apache or nginx) on the same device.
      8 
      9 ## Learn more
     10 
     11 => gemini://qwertqwefsday.eu/agate.gmi Home page
     12 => https://crates.io/crates/agate Agate on crates.io
     13 => https://github.com/mbrubeck/agate Source code
     14 
     15 ## Installation and Setup
     16 
     17 1. Get a binary for agate. You can use any of the below ways:
     18 
     19 ### Pre-compiled
     20 
     21 Download and unpack the [pre-compiled binary](https://github.com/mbrubeck/agate/releases).
     22 
     23 ### NixOS/Nix
     24 
     25 Using the nix package manager run `nix-env -i agate`
     26 
     27 _Note:_ agate is currently only in the unstable channel and will reach a release channel once the next release is tagged
     28 
     29 ### Guix System
     30 
     31 Deploy agate with GNU Guix System by adding the agate-service-type to your system services.
     32 => https://dataswamp.org/~solene/2021-06-17-guix-gemini.html refer to this article
     33 
     34 see also
     35 => https://guix.gnu.org/manual/en/html_node/Web-Services.html Guix Manual Web-Services
     36 => https://guix.gnu.org/manual/en/html_node/Services.html Guix Manual Services
     37 
     38 ### Arch Linux
     39 
     40 Install the package "agate-bin" from AUR for pre-compiled binary. Otherwise install the "agate" package from AUR to get agate compiled from source.
     41 
     42 ### Cargo
     43 
     44 If you have the Rust toolchain installed, run `cargo install agate` to install agate from crates.io.
     45 
     46 ### Source
     47 
     48 Download the source code and run `cargo build --release` inside the source repository, then find the binary at `target/release/agate`.
     49 
     50 ***
     51 You can use the install script in the `tools` directory for the remaining steps if there is one for your system. If there is none, please consider contributing one to make it easier for less tech-savvy users!
     52 ***
     53 
     54 2. Run the server. You can use the following arguments to specify the locations of the content directory, IP address and port to listen on, host name to expect in request URLs, and default language code to include in the MIME type for text/gemini files: (Replace the hostname `example.com` with the address of your Gemini server.)
     55 If you have not done it yourself, Agate will generate a private key and certificate for you on the first run, using the specified hostname(s). See the section Certificates below for more.
     56 
     57 ```
     58 agate --content path/to/content/ \
     59       --addr [::]:1965 \
     60       --addr 0.0.0.0:1965 \
     61       --hostname example.com \
     62       --lang en-US
     63 ```
     64 
     65 All of the command-line arguments are optional.  Run `agate --help` to see the default values used when arguments are omitted.
     66 
     67 When a client requests the URL `gemini://example.com/foo/bar`, Agate will respond with the file at `path/to/content/foo/bar`. If any segment of the requested path starts with a dot, agate will respond with a status code 52, whether the file exists or not. This behaviour can be disabled with `--serve-secret` or by an entry for the specific file in the `.meta` configuration file (see Meta-Presets). If there is a directory at that path, Agate will look for a file named `index.gmi` inside that directory.
     68 
     69 ## Configuration
     70 
     71 ### Automatic Certificate generation
     72 
     73 If the `--hostname` argument is used, Agate will generate keys and self signed certificates for each hostname specified. For Gemini it is recommended by the specification to use self signed certificates because Gemini uses the TOFU (Trust on first use) principle for certificates. Because of this, the generated certificates will also have a long expiration time of `4096-01-01`.
     74 
     75 For manual configuration of keys and certificates see the section on certificates below.
     76 
     77 ### TLS versions
     78 
     79 Agate by default supports TLSv1.2 and TLSv1.3. You can disable support for TLSv1.2 by using the flag `--only-tls13` (or its short version `-3`). This is *NOT RECOMMENDED* as it may break compatibility with some clients. The Gemini specification requires compatibility with TLSv1.2 "for now" because not all platforms have good support for TLSv1.3 (cf. §4.1 of the specification).
     80 
     81 ### Directory listing
     82 
     83 You can enable a basic directory listing for a directory by putting a file called `.directory-listing-ok` in that directory. This does not have an effect on sub-directories.
     84 This file must be UTF-8 encoded text; it may be empty. Any text in the file will be prepended to the directory listing.
     85 The directory listing will hide files and directories whose name starts with a dot (e.g. the `.directory-listing-ok` file itself, the `.meta` configuration file, or the `..` directory).
     86 
     87 A file called `index.gmi` will always take precedence over a directory listing.
     88 
     89 ### Meta-Presets
     90 
     91 You can put a file called `.meta` in any content directory. This file stores some metadata about the adjacent files which Agate will use when serving these files. The `.meta` file must be UTF-8 encoded.
     92 You can also enable a central configuration file with the `-C` flag (or the long version `--central-conf`). In this case Agate will always look for the `.meta` configuration file in the content root directory and will ignore `.meta` files in other directories.
     93 
     94 The `.meta` file has the following format [1]:
     95 * Empty lines are ignored.
     96 * Everything behind a `#` on the same line is a comment and will be ignored.
     97 * All other lines must have the form `<path>:<metadata>`, i.e. start with a file path, followed by a colon and then the metadata.
     98 
     99 `<path>` is a case sensitive file path, which may or may not exist on disk. If <path> leads to a directory, it is ignored.
    100 If central configuration file mode is not used, using a path that is not a file in the current directory is undefined behaviour (for example `../index.gmi` would be undefined behaviour).
    101 You can use Unix style patterns in existing paths. For example `content/*` will match any file within `content`, and `content/**` will additionally match any files in subdirectories of `content`.
    102 However, the `*` and `**` globs on their own will by default not match files or directories that start with a dot because of their special meaning.
    103 This behaviour can be disabled with `--serve-secret` or by explicitly matching files starting with a dot with e.g. `content/.*` or `content/**/.*` respectively.
    104 For more information on the patterns you can use, please see the documentation of `glob::Pattern`.
    105 Rules can overwrite other rules, so if a file is matched by multiple rules, the last one applies.
    106 
    107 => https://docs.rs/glob/0.3.0/glob/struct.Pattern.html Documentation of `glob::Pattern`.
    108 
    109 `<metadata>` can take one of four possible forms:
    110 1. empty:
    111 Agate will not send a default language parameter, even if it was specified on the command line.
    112 2. starting with a semicolon followed by MIME parameters:
    113 Agate will append the specified string onto the MIME type, if the file is found.
    114 3. starting with a gemini status code (i.e. a digit 1-6 inclusive followed by another digit) and a space:
    115 Agate will send the metadata whether the file exists or not. The file will not be sent or accessed.
    116 4. a MIME type, may include parameters:
    117 Agate will use this MIME type instead of what it would guess, if the file is found. The default language parameter will not be used, even if it was specified on the command line.
    118 
    119 If a line violates the format or looks like case 3, but is incorrect, it might be ignored. You should check your logs. Please know that this configuration file is first read when a file from the respective directory is accessed. So no log messages after startup does not mean the `.meta` file is okay.
    120 
    121 Such a configuration file might look like this:
    122 
    123 ```
    124 # This line will be ignored.
    125 **/*.de.gmi: ;lang=de
    126 nl/**/*.gmi: ;lang=nl
    127 index.gmi: ;lang=en-GB
    128 LICENSE: text/plain;charset=UTF-8
    129 gone.gmi: 52 This file is no longer here, sorry.
    130 ```
    131 
    132 If this is the `.meta` file in the content root directory and the `-C` flag is used, this will result in the following response headers:
    133 
    134 ```
    135 `/` or `/index.gmi`
    136     -> `20 text/gemini;lang=en-GB`
    137 `/LICENSE`
    138     -> `20 text/plain;charset=UTF-8`
    139 `/gone.gmi`
    140     -> `52 This file is no longer here, sorry.`
    141 any non-hidden file ending in `.de.gmi` (including in non-hidden subdirectories)
    142     -> `20 text/gemini;lang=de`
    143 any non-hidden file in the `nl` directory ending in `.gmi` (including in non-hidden subdirectories)
    144     -> `20 text/gemini;lang=nl`
    145 ```
    146 
    147 [1] In theory the syntax is that of a typical INI-like file and also allows for sections with `[section]` (the default section is set to `mime` in the parser), since all other sections are disregarded, this does not make a difference. This also means that you can in theory also use `=` instead of `:`. For even more information, you can visit the documentation of `configparser`.
    148 => https://docs.rs/configparser/2.0 documentation of `configparser`
    149 
    150 ### Logging Verbosity
    151 
    152 Agate uses the `env_logger` crate and allows you to set the logging verbosity by setting the `RUST_LOG` environment variable. To turn off all logging use `RUST_LOG=off`. For more information, please see the documentation of `env_logger`.
    153 => https://docs.rs/env_logger/0.8 documentation of `env_logger` crate
    154 
    155 ### Virtual Hosts
    156 
    157 Agate has basic support for virtual hosts. If you specify multiple `--hostname`s, Agate will look in a directory with the respective hostname within the content root directory.
    158 For example if one of the hostnames is `example.com`, and the content root directory is set to the default `./content`, and `gemini://example.com/file.gmi` is requested, then Agate will look for `./content/example.com/file.gmi`. This behaviour is only enabled if multiple `--hostname`s are specified.
    159 Agate also supports different certificates for different hostnames, see the section on certificates below.
    160 
    161 If you want to serve the same content for multiple domains, you can instead disable the hostname check by not specifying `--hostname`. In this case Agate will disregard a request's hostname apart from checking that there is one.
    162 
    163 When one or more `--hostname`s are specified, Agate will check that the hostnames and port in request URLs match the specified hostnames and the listening ports. If Agate is behind a proxy on another port and receives a request with an URL specifying the proxy port, this port may not match one of Agate's listening ports and the request will be rejected: it is possible to disable the port check with `--skip-port-check`.
    164 
    165 ### Certificates
    166 
    167 Agate has support for using multiple certificates with the `--certs` option. Agate will thus always require that a client uses SNI, which should not be a problem since the Gemini specification also requires SNI to be used.
    168 
    169 Certificates are by default stored in the `.certificates` directory. This is a hidden directory for the purpose that uncautious people may set the content root directory to the current directory which may also contain the certificates directory. In this case, the certificates and private keys would still be hidden. The certificates are only loaded when Agate is started and are not reloaded while running. The certificates directory may directly contain a key and certificate pair, this is the default pair used if no other matching keys are present. The certificates directory may also contain subdirectories for specific domains, for example a folder for `example.org` and `portal.example.org`. Note that the subfolders for subdomains (like `portal.example.org`) should not be inside other subfolders but directly in the certificates directory. Agate will select the certificate/key pair whose name matches most closely. For example take the following directory structure:
    170 
    171 ```
    172 .certificates
    173 |-- cert.der     (1)
    174 |-- key.der      (1)
    175 |-- example.org
    176 |   |-- cert.der (2)
    177 |   `-- key.der  (2)
    178 `-- portal.example.org
    179     |-- cert.der (3)
    180     `-- key.der  (3)
    181 ```
    182 
    183 This would be understood like this:
    184 * The certificate/key pair (1) would be used for the entire domain tree (exceptions below).
    185 * The certificate/key pair (2) would be used for the entire domain tree of `example.org`, so also including subdomains like `secret.example.org`. It overrides the pair (1) for this subtree (exceptions below).
    186 * The certificate/key pair (3) would be used for the entire domain tree of `portal.example.org`, so also inclduding subdomains like `test.portal.example.org`. It overrides the pairs (1) and (2) for this subtree.
    187 
    188 Using a directory named just `.` causes undefined behaviour as this would have the same meaning as the top level certificate/key pair (pair (1) in the example above).
    189 
    190 The files for a certificate/key pair have to be named `cert.der` and `key.der` respectively. The certificate has to be a X.509 certificate in a DER format file and has to include a subject alt name of the domain name. The private key has to be in DER format and must be either an RSA, ECDSA or Ed25519 key.
    191 
    192 ## Logging
    193 
    194 All requests via TCP sockets will be logged using this format:
    195 ```
    196 <local ip>:<local port> <remote ip or dash> "<request>" <response status> "<response meta>"[ error:<error>]
    197 ```
    198 All requests via Unix sockets will be logged using this format:
    199 ```
    200 unix:[<unix socket name>] - "<request>" <response status> "<response meta>"[ error:<error>]
    201 ```
    202 Square brackets indicate optional parts.
    203 
    204 The "error:" part will only be logged if an error occurred. This should only be used for informative purposes as the status code should provide the information that an error occurred. If the error consisted in the connection not being established (e.g. because of TLS errors), special status codes listed below may be used.
    205 
    206 By default, Agate will not log the remote IP addresses because that might be an issue because IPs are considered private data under the EU's GDPR. To enable logging of IP addresses, you can use the `--log-ip` option. Note that in this case some error conditions might still force Agate to log a dash instead of an IP address. IP addresses can also not be logged for connections via Unix sockets.
    207 
    208 There are some lines apart from these that might occur in logs depending on the selected log level. For example the initial "Listening on..." line or information about listing a particular directory.
    209 
    210 Agate uses some status codes that are not valid Gemini status codes when logging errors:
    211 * 00 - there was an error establishing the TLS connection
    212 * 01 - there was an error in fetching the peer's IP address
    213 
    214 ## Security considerations
    215 
    216 If you want to run agate on a multi-user system, you should be aware that all certificate and key data is loaded into memory and stored there until the server stops. Since the memory is also not explicitly overwritten or zeroed after use, the sensitive data might stay in memory after the server has terminated.
    217 
    218 # Changelog
    219 
    220 All notable changes to this project will be documented in this file.
    221 
    222 The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
    223 => https://keepachangelog.com/en/1.0.0/ Keep a Changelog home page
    224 => https://semver.org/spec/v2.0.0.html Semantic versioning standard v2.0.0
    225 
    226 ## [3.3.1] - 2023-08-05
    227 Thank you to Jan Stępień and @michaelnordmeyer for contributing to this release.
    228 
    229 ### Fixed
    230 * set permissions for generated key files so only owner can read them
    231 * improve documentation and tests
    232 
    233 ## [3.3.0] - 2023-03-18
    234 Thank you to @equalsraf, @michaelnordmeyer and @wanderer1988 for contributing to this release.
    235 
    236 ### Added
    237 * listening on unix sockets (#244)
    238 
    239 ### Fixed
    240 * updated dependencies
    241 * misstyped email address in section on how to report security vulnerabilities (#239)
    242 * wrong language code in README (#189)
    243 
    244 ## [3.2.4] - 2022-05-18
    245 Thank you to @06kellyjac, @albertlarsan68 and @kahays for contributing to this release.
    246 
    247 ### Fixed
    248 * removed port collisions in tests, for the last time (#143)
    249 * fixed Dockerfile startup command (#169)
    250 * upated dependencies
    251 
    252 ## [3.2.3] - 2022-02-04
    253 Thank you to T. Spivey for contributing to this release.
    254 
    255 ### Fixed
    256 * improper IRIs are handled instead of crashing (bug reported via email)
    257 * updated dependencies
    258 
    259 ## [3.2.2] - 2022-01-25
    260 Thank you to @Suzie97 for contributing to this release.
    261 
    262 ### Added
    263 * CI build for `aarch64-apple-darwin` target (#137)
    264 
    265 ### Fixed
    266 * updated dependencies
    267 
    268 ## [3.2.1] - 2021-12-02
    269 Thank you to @MatthiasPortzel for contributing to this release.
    270 
    271 ### Fixed
    272 * host name comparisons are now case insensitive (#115)
    273 * made automatic certificate generation more prominent in the README
    274 * updated dependencies
    275 
    276 ## [3.2.0] - 2021-11-15
    277 Thank you to @balazsbtond and @joseph-marques for contributing to this release.
    278 
    279 ### Added
    280 * you can add header text to a directory listing. See the updated instructions above for details. (#98)
    281 
    282 ### Fixed
    283 * updated dependencies
    284 * error pages also send close_notify (#100)
    285 
    286 ## [3.1.3] - 2021-10-25
    287 Thank you to @FoxKyong for contributing to this release.
    288 
    289 ### Fixed
    290 * the fix for dual stack listening from 3.1.2 was executed asynchronously and would thus
    291   sometimes fail. starting the listeners on different socket addresses is now synchronous
    292   (#79)
    293 
    294 ## [3.1.2] - 2021-10-15
    295 Thank you to @etam for contributing to this release.
    296 
    297 ### Fixed
    298 * when starting up on a system that automatically listens in dual stack mode (e.g. some
    299   linux distributions seem to do this), detect a second unspecified address to not cause
    300   the "address in use" error with the default listening addresses
    301 * updated a dependency
    302 
    303 ## [3.1.1] - 2021-10-14
    304 Thank you to @jgarte and @alvaro-cuesta for contributing to this release.
    305 
    306 ### Added
    307 * running Agate using GNU Guix (#62)
    308 
    309 ### Fixed
    310 * actually bind to multiple IP addresses. Despite the documentation saying so,
    311   Agate would only bind to the first address that did not result in an error. (#63)
    312 * updated dependencies
    313 
    314 ## [3.1.0] - 2021-06-08
    315 Thank you to Matthew Ingwersen and Oliver Simmons (@GoodClover) for contributing to this release.
    316 
    317 ### Added
    318 * tests for symlink files (#60)
    319   Symlinks were already working before.
    320 
    321 ### Fixed
    322 * A path traversal security issue was closed: Percent encoded slashes were misunderstood.
    323 
    324 ### Changed
    325 * Visiting a directory without `index.gmi` and `.directory-listing-ok` now returns a different error message to better show the cause of the error.
    326   To retain the current behaviour of showing a `51 Not found, sorry.` error, add the following line to the respective directories' `.meta` file:
    327 ```
    328 index.gmi: 51 Not found, sorry.
    329 ```
    330 
    331 ## [3.0.3] - 2021-05-24
    332 Thank you to @06kellyjac, @cpnfeeny, @lifelike, @skittlesvampir and @steko for contributing to this release.
    333 
    334 ### Added
    335 * Dockerfile for compiling Agate from source (#52, #53, #56, #57)
    336 
    337 ### Fixed
    338 * If the remote IP address can not be fetched, log an error instead of panicking.
    339   The previous handling could be exploited as a DoS attack vector. (#59)
    340 * Two tests were running on the same port, causing them to fail nondeterministically. (#51)
    341 * Rephrased the changelog for 3.0.0 on continuing to use older certificates. (#55)
    342 * Updated dependencies.
    343 
    344 ## [3.0.2] - 2021-04-08
    345 Thank you to @kvibber, @lifelike and @pasdechance for contributing to this release.
    346 
    347 ### Changed
    348 * The new specfication changes are obeyed regarding rejecting request URLs that contain fragments or userinfo parts.
    349 * The default signature algorithm used for generating certificates has been changed to ECDSA since there were multiple complaints about Ed25519.
    350 
    351 ## [3.0.1] - 2021-03-28
    352 Thank you to @MidAutumnMoon and @steko for contributing to this release.
    353 
    354 ### Added
    355 * Installation instructions for Arch Linux from Arch User Repositories. (#47)
    356 
    357 ### Fixed
    358 * The certificate file extensions in the README example. (#45)
    359 * The certificate directory is automatically created if it does not exist. (#44)
    360 
    361 ## [3.0.0] - 2021-03-27
    362 Thank you to @ddevault for contributing to this release.
    363 
    364 ### Added
    365 * Support for ECDSA and Ed25519 keys.
    366 * Agate now generates certificates and keys for each `--hostname` that is specified but no matching files exist. (#41)
    367 
    368 ### Changed
    369 * The ability to specify a certificate and key with `--cert` and `--key` respectively has been replaced with the `--certs` option. (#40)
    370   Certificates are now stored in a special directory. To migrate to this version, the keys should be stored in the `.certificates` directory (or any other directory you specify).
    371   This enables us to use multiple certificates for multiple domains.
    372   Note that if you want to continue to use your old certificates (recommended because of TOFU), they probably lack the `subjectAltName` directive so your old certificates should be placed at the top level of the certificates directory. Otherwise you will get an error similar to this: "The certificate file for example.com is malformed: unexpected error: The server certificate is not valid for the given name"
    373 * The certificate and key file format has been changed from PEM to DER. This simplifies loading certificate and key files without relying on unstable portions of other crates.
    374   If you want to continue using your existing certificates and keys, please convert them to DER format. You should be able to use these commands if you have openssl installed:
    375 ```
    376 openssl x509 -in cert.pem -out cert.der -outform DER
    377 openssl rsa -in key.rsa -out key.der -outform DER
    378 ```
    379   Since agate will automatically generate certificates from now on, the different format should not be a problem because users are not expected to handle certificates unless experienced enough to be able to handle DER formatting as well.
    380 
    381 ### Fixed
    382 * Agate now requires the use of SNI by any connecting client.
    383 * All log lines are in the same format now:
    384   `<local ip>:<local port> <remote ip or dash> "<request>" <response status> "<response meta>" [error:<error>]`
    385   If the connection could not be established correctly (e.g. because of TLS errors), the status code `00` is used.
    386 * Messages from modules other than Agate itself are not logged by default.
    387 
    388 ## [2.5.3] - 2021-02-27
    389 Thank you to @littleli and @06kellyjac for contributing to this release.
    390 
    391 ### Added
    392 * Automated tests have been added so things like 2.5.2 should not happen again (#34).
    393 * Version information flag (`-V` or `--version` as conventional with e.g. cargo)
    394 
    395 ### Changed
    396 * Forbid unsafe code. (There was none before, just make it harder to add some.)
    397 * When logging remote IP addresses, the port is now never logged, which also changes the address format.
    398 
    399 ### Fixed
    400 * Updated `url` to newest version, which resolves a TODO.
    401 * The help exits successfully with `0` rather than `1` (#37).
    402 * The GitHub workflow has been fixed so Windows binaries are compressed correctly (#36).
    403 * Split out install steps to allow for more options in the future.
    404 * Add install notes for nix/NixOS to the README (#38).
    405 * Updated dependencies.
    406 
    407 ## [2.5.2] - 2021-02-12
    408 
    409 ### Fixed
    410 * Semicolons are no longer considered to be starting a comment in `.mime` files.
    411 
    412 ## [2.5.1] - 2021-02-12
    413 Functionally equivalent to version 2.5.1, only releasing a new version to update README on crates.io.
    414 
    415 ### Fixed
    416 * Fixed mistakes in the README.
    417 
    418 ## [2.5.0] - 2021-02-12
    419 Agate now has an explicit code of conduct and contributing guidelines.
    420 Thank you to @ERnsTL, @gegeweb, @SuddenPineapple, and @Ylhp for contributing to this release.
    421 
    422 ### Added
    423 * You can now supply multiple `--hostname`s to enable basic vhosts (#28, #31).
    424 * Disabling support for TLSv1.2 can now be done using the `--only-tls13` flag, but this is *NOT RECOMMENDED* (#12).
    425 * The tools now also contain a startup script for FreeBSD (#13).
    426 * Using central config mode (flag `-C`), all configuration can be done in one `.meta` file (see README.md for details).
    427 * The `.meta` configuration file now allows for globs to be used.
    428 
    429 ### Changed
    430 * The `.meta` file parser now uses the `configparser` crate. The syntax does not change.
    431 * The changelog is now also kept in this file in addition to the GitHub releases.
    432 * Certificate chain and key file are now only loaded once at startup, certificate changes need a restart to take effect.
    433 * Hidden files are now served if there is an explicit setting in a `.meta` file for them, regardless of the `--serve-secret` flag.
    434 
    435 ### Fixed
    436 * The Syntax for the IPv6 address in the README has been corrected.
    437 * Give a better error message when no keys are found in the key file instead of panicking with a range check (#33).
    438 
    439 ## [2.4.1] - 2020-02-08
    440 ### Fixed
    441 * Re-enabled multiple occurrences of `--addr`. This was accidentally disabled by a merge.
    442 
    443 ## [2.4.0]+podman.build - 2020-02-06
    444 This is the same as [2.4.0], only the build process has been changed so it should accommodate a wider range of architectures and devices.
    445 
    446 ## [2.4.0] - 2020-02-06
    447 Since there is a new maintainer (@Johann150), the range in pre-compiled binaries has changed a bit.
    448 
    449 ### Added
    450 * Added some installation tools for Debian.
    451 * Added a sidecar file for specifying languages, MIME media types or complete headers on a per file basis (#16).
    452 
    453 ### Changed
    454 * Improved logging output. Agate now also respects the `RUST_LOG` environment variable, so you can configure the log level (#22, #23).
    455 
    456 ## [2.3.0] - 2020-01-17
    457 Thanks to @Johann150.
    458 
    459 ### Changed
    460 * Combine address and port back into a single command-line argument (#21).
    461 
    462 ## [2.2.0] - 2020-01-16
    463 Thank you to @gegeweb, @Johann150 and @purexo for contributing to this release.
    464 
    465 ### Changed
    466 * Split address and port into separate command-line parameters.
    467 
    468 ### Fixed
    469 * Listen on both IPv6 and IPv4 interfaces by default (#14, #15).
    470 * Do not serve files whose path contains a segment starting with a dot (#17, #20).
    471 * Fix redirects of URLs with query strings (#19).
    472 
    473 ## [2.1.3] - 2020-01-02
    474 ### Changed
    475 * Switch to the Tokio async run time.
    476 
    477 ### Fixed
    478 * Send TLS close-notify message when closing a connection.
    479 * Require absolute URLs in requests.
    480 
    481 ## [2.1.2] - 2020-01-01
    482 ### Fixed
    483 * More complete percent-encoding of special characters in filenames.
    484 * Minor improvements to error logging.
    485 * Internal code cleanup.
    486 
    487 ## [2.1.1] - 2020-12-31
    488 ### Changed
    489 * List directory content in alphabetical order.
    490 
    491 ### Fixed
    492 * Handle percent-escaped paths in URLs.
    493 * Percent-escape white space characters in directory listings.
    494 
    495 ## [2.1.0] - 2020-12-29
    496 * Enabled GitHub Discussions. If you are using Agate, please feel free to leave a comment to let us know about it!
    497 Thank you to @Johann150 and @KilianKemps for contributing to this release.
    498 
    499 ### Added
    500 * Optional directory listings (#8, #9).
    501 
    502 ### Fixed
    503 * Updated dependencies.
    504 
    505 ## [2.0.0] - 2020-12-23
    506 Thank you to @bortzmeyer, @KillianKemps, and @Ylhp for contributing to this release.
    507 
    508 ### Added
    509 * New `--language` option to add a language tag to the MIME type for text/gemini responses (#6).
    510 
    511 ### Changed
    512 * New format for command-line options. See the documentation or run `agate --help` for details.
    513 * Logging is enabled by default. Use the `--silent` flag to disable it.
    514 * Pre-compiled binaries are built with the [`cross`](https://github.com/rust-embedded/cross) tool, for better compatibility with older Linux systems.
    515 
    516 ## [1.3.2] - 2020-12-09
    517 This release is functionally identical to Agate 1.3.1, and users of that version do not need to update.
    518 
    519 ### Fixed
    520 * Update to async-tls 0.11 because the previous version was yanked.
    521 
    522 ## [1.3.1] - 2020-12-08
    523 Thanks @dcreager for contributing this fix.
    524 
    525 ### Fixed
    526 * Updated dependencies to fix `cargo install` (#7).
    527 
    528 ## [1.3.0] - 2020-11-20
    529 Thank you @Johann150, @jonhiggs and @tronje for contributing to this release!
    530 
    531 ### Fixed
    532 * verify hostname and port in request URL (#4).
    533 * improved logging (#2, #3).
    534 * Don't redirect to "/" when the path is empty (#5).
    535 * Update dependencies.
    536 
    537 ## [1.2.2] - 2020-09-21
    538 Thank you to @m040601 for contributing to this release.
    539 
    540 ### Changed
    541 * Switch from `tree_magic` to `mime_guess` for simpler MIME type guessing.
    542 * Built both x86_64 and ARM binaries. These binaries are built for Linux operating systems with glibc 2.28 or later, such as Debian 10 ("buster") or newer, Ubuntu 18.10 or newer, and Raspberry Pi OS 2019-06-20 or newer (#1).
    543 
    544 ### Fixed
    545 * Update dependencies.
    546 * Minor internal code cleanup.
    547 
    548 ## [1.2.1] - 2020-06-20
    549 ### Fixed
    550 * Reduce memory usage when serving large files.
    551 * Update dependencies.
    552 
    553 ## [1.2.0] - 2020-06-10
    554 ### Changed
    555 * text/gemini filename extension from `.gemini` to `.gmi`.
    556 
    557 ### Fixed
    558 * Handling for requests that exceed 1KB.
    559 * Reduce memory allocations and speed up request parsing.
    560 * Update dependencies.
    561 
    562 ## [1.1.0] - 2020-05-22
    563 ### Added
    564 * Auto-detect MIME types.
    565 
    566 ## [1.0.1] - 2020-05-21
    567 ### Added
    568 * Send more accurate error codes for unsupported requests.
    569 * Do more validation of request URLs.
    570 
    571 ## [1.0.0] - 2020-05-21