README
¶
ircv3-filehost-server
ircv3-filehost-server is a standalone implementation of the HTTP-based file upload protocol defined in soju.im/FILEHOST and draft/FILEHOST specifications. It supports authentication and can be used in certain production workloads provided the limitations are well understood.
Installation
You can install ircv3-filehost-server using one of the following methods:
-
Downloading a binary. You can download the latest build or pick a release.
-
Installing from source. First, install Go 1.25 or newer. Then run:
$ go install codeberg.org/whitequark/ircv3-filehost-server@latest -
Using the Nix flake. If you already use Nix, you can use the provided flake.
Usage
You will need to configure ircv3-filehost-server first, which is done using a config.toml TOML file.
When a configuration option is described below as [section].key = "value", write the following in the config.toml file:
[section]
key = "value"
Configuring authentication
Before you can use ircv3-filehost-server you must pick an authentication method. This (single) method will determine who can upload files; downloads are not access-controlled. The following methods are currently implemented:
-
[auth].type = "none": No authentication is performed. Servers using this method must never be exposed to the open internet.When using this method, files are assigned URLs of the form
/upload/anonymous/<filename...>(by default). -
[auth].type = "sasl": SASL authentication is performed against the specified server. Additional configuration:[auth.sasl] server = "irc[s]://<server>[:port]" allowlist = []The flow of this method follows:
- Credentials are extracted from an
Authorization: BasicHTTP request header. If the username or the password are empty, the upload is denied. - If
[auth.sasl].allowlistcontains a non-empty list of usernames, and the authorization username is not in the list, the upload is denied. - A new connection to the IRC server is established and an attempt is made to authenticate using the SASL PLAIN method. If it succeeds, the upload is allowed, else it is denied.
[!IMPORTANT] If the filehost server is connecting to the IRC server over a public network, make sure you are using an
ircs://scheme.When using this method, files are assigned URLs of the form
/upload/user/<username>/<filename...>(by default). - Credentials are extracted from an
-
[auth].type = "proxy": Authentication is assumed to be performed by a reverse proxy and passed to the server. Servers using this method must never be exposed to the open internet, and require additional configuration on the proxy server. Additional configuration:[auth.proxy] header = "<header-name>" allowlist = []The username of the authenticated user must be provided by the reverse proxy using the header in
[auth.proxy].header(default"X-Remote-User"). Similar to SASL authentication,[auth.proxy].allowlistcan be used to restrict which users are permitted to upload files.When using this method, files are assigned URLs of the form
/upload/user/<username>/<filename...>(by default).
Configuring other options
The following other options are provided by ircv3-filehost-server:
-
[data].root = "<root>"(default"./data"): Uploaded files are stored under<root>. This directory will be created if it does not exist.All files inside it are exposed via HTTP: a
GET /upload/<path>request will retrieve the file<root>/<path>. If you are migrating from a different file server, you could copy the existing data here. -
[data].strip-exif = <strip>(defaulttrue): EXIF metadata (except for orientation) is opportunistically removed from image files during upload if they are in the JPEG, PNG, or WebP format.[!IMPORTANT] This is not a guarantee; there are other file formats which can contain sensitive EXIF metadata (e.g. HEIC files) yet will remain unprocessed.
This feature is not available and must be explicitly turned off when the project is built with
-tags=no_gpl; see caveats. -
[http].listen = "<protocol>/<host>:<port>"(default"tcp/localhost:8080"): HTTP server will listen on the specified endpoint.To use a Unix socket instead, use e.g.
[http].listen = "unix//tmp/filehost.sock". -
[http].upload-path = "<path>"(default"/upload"): HTTP server will accept uploads on the specified path.If you use a dedicated sub-domain for uploads (which is recommended for security reasons), you can shorten the generated URLs by removing the redundant
/uploadpath fragment. -
[http].cors-origins = <origins>(default[]): allowed HTTP origins for cross-origin requests.Specify HTTP origins here for all WebIRC clients that should be able to upload files; for example:
[http] cors-origins = ["https://irc.mynetwork.example"] -
[limit].file-size = "<size>"(default"1MB"): per-file size limit. Uploads larger than this value will be rejected without processing.
Integrating with the IRCd
An IRC client needs to be either configured explicitly to use the filehost server (which is out of scope for this document), or it can learn this from the ISUPPORT message response. Some IRCv3 servers allow customizing this response.
For [Ergo], add the following options to ircd.yaml:
server:
additional-isupport:
"soju.im/FILEHOST": "https://files.mynetwork.example/upload"
"draft/FILEHOST": "https://files.mynetwork.example/upload"
Running as a service
The following configuration files can be used as a basis for your own configuration.
/etc/systemd/system/ergochat-filehost.service:
[Unit]
Description=ergochat filehost server
After=network-online.target
Requires=network-online.target
[Install]
WantedBy=ergochat.service
[Service]
DynamicUser=true
StateDirectory=filehost
ExecStart=/usr/bin/ircv3-filehost-server -c /etc/ergochat-filehost.conf
Restart=on-failure
RestartSec=5s
/etc/ergochat-filehost.conf:
[data]
root = "/var/lib/private/filehost/data"
[auth]
type = "sasl"
[auth.sasl]
server = "ircs://irc.mynetwork.example"
Deploying on the Web
There are two options for exposing ircv3-filehost-server on the open internet:
-
Behind a reverse proxy server like nginx or Caddy.
For nginx, the following configuration can be used as inspiration:
server { listen 443 ssl; server_name files.mynetwork.example; location /upload { proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://localhost:8080; proxy_pass_header Server; proxy_request_buffering off; } }The correspondng ircv3-filehost-server
config.tomlcould be:[http] listen = "tcp/localhost:8080" # no [http.acme] or [http.tls] -
Terminating TLS in ircv3-filehost-server itself.
Certificates are acquired automatically using Let's Encrypt. Update the configuration to include your email address, domain name, and cache directory. The cache directory will be populated with sensitive cryptographic data.
[http] listen = "tcp/:443" [http.acme] email = "operator@mynetwork.example" domain = "mynetwork.example" secrets = "/var/lib/private/filehost/acme"It is also possible to provide a certificate and keyfile manually:
[http] listen = "tcp/:443" [http.tls] crt = "../path/to/domain.crt" key = "../path/to/domain.key"These two methods are mutually exclusive.
[!WARNING]
Note that (regardless of the deployment method) the domain from which files are served (in this example,
files.mynetwork.example) must not be shared with the domain of a webirc client (if any) (in this example, it could behttps://irc.mynetwork.example/webirc). It is possible to upload HTML or JavaScript files and they will be served with the correspondingContent-Type; the same-origin policy will prevent such code from stealing webirc secrets, but only if the files are served from a separate domain.
Success!
You now have a fully functioning IRC file upload host. Make sure to read through the limitations.
Limitations
This project has certain limitations:
- There are no storage quotas, whether per-user or per-server. The per-upload file size limit is configured
[limit].file-size, but quotas currently cannot be enforced at all. With[auth].type = "sasl"and[auth].type = "proxy", files are stored separately in user-specific directories. - There are no limits on file types. It is quite difficult to unambiguously determine the type of a file, so the author chose not to do it. There are some
Content-Types that may be worth never returning (such astext/html) due to potential for XSS. - Links to uploaded files are valid forever. This is a limitation of the specification (rather than the implementation), but it is still worth mentioning; nothing stops an IRC user from employing the filehost server as a kind of CDN.
Make sure you understand the implications of the issues above before exposing a server to the open internet. It is not recommended to use ircv3-filehost-server on IRC servers with open registration, or, generally, in adversarial environments.
License
0-clause BSD. Unless built with -tags=no_gpl, the executable is subject to terms of GNU Affero General Public License 3.0.
Documentation
¶
There is no documentation for this package.