A simple, fast, and easy to use static file server

Related tags

Command-line chimney
Overview

Warning

This is still in early development, I would not recommend for production use.. yet.

See the issues for things that are on the "roadmap" or missing

This may not fit your usecase, have a look at Nginx and Caddy

A minimal static file server. See this example deployed on Fly.

Goals

  • As tiny as possible
  • Reasonably fast
  • Serve files with the correct mime-types
  • Predictable "routing" (the way you will expect it from like Nginx or Apache eg. if /foo is a folder, it should resolve fine to /foo/index.html)
  • Rewrites and redirects should just work out of the box
  • Little to no "would be nice" features (re goal one)
  • Easily usable yet lean as an OCI image (this is more for the project I made it for, may not matter to anyone else)

Installation

With Docker

You can run the Docker image and provide a bind mount like this:

docker pull ghcr.io/aosasona/chimney:latest
docker run -p 80:80 -v ./dist:/var/www/html ghcr.io/aosasona/chimney:latest

Although, a more practical (and recommended) usage is to use it in a multi-stage build Dockerfile, this is a Dockerfile for an Astro website:

FROM node:18-alpine AS build

WORKDIR /app

COPY package.json pnpm-lock.yaml .

# Install pnpm package manager and install dependencies
RUN npm install -g pnpm

RUN pnpm install

# Copy files needed for the build, source directory and public folder
COPY astro.config.mjs tsconfig.json tailwind.config.cjs .

COPY src src

COPY public public

# Build to static HTML
RUN pnpm build

# Use chimney as final run image
FROM ghcr.io/aosasona/chimney:latest

# Copy the result of the previous build process (HTML files and the asssets; JS, CSS, Images, GIFs etc) to the default public directory
COPY --from=build /app/dist /var/www/html

# Replace the default config with our custom config
COPY chimney.toml /etc/chimney/chimney.toml

EXPOSE 80

# Start the proxy
CMD ["run"]

Directories

If you are using the official image, there are a few locations you might want to know about:

Path Description
/var/www/html Similar to NGINX, this is where all your publicly available files should be, including any asset. This path was chosen since it is familiar to most people, you can change this by overriding the default config and setting root_dir to anywhere you want in the container
/etc/chimney/chimney.toml This is where the default config lives, you can change this by copying your own config to wherever you desire and writing CMD as ["run", "-c", "path/to/config"] in your custom Dockerfile
/bin/chimney This is where the Chimney binary lives in the container, since the ENTRYPOINT has been set to this path, you can easily use the "docker run" command to execute commands in the container directly without specifying /bin/chimney

As a standalone binary

Currently, there is no way to install via Homebrew or Cargo (this may change in the future), but you can download the binary for your platform from the releases page. If you are using Windows, there are no builds available so you could try using the next option.

Build from source

If you are unable to or don't want to use Docker and there are no builds available for your platform, you can use Chimney by building from source:

git clone https://github.com/aosasona/chimney.git
cd chimney
cargo build --release

# and then run it
./target/release/chimney run

Usage

chimney init path/to/project
chimney run -c path/to/project/chimney.toml # the config filename is optional, it looks for `chimney.toml` by default in the target directory

Config reference

Warning

HTTPS functionality has NOT been implemented yet, so using this standalone in production is kind of not feasible... unless you have some sort of central proxy and a bunch of containers running Chimney that you simply proxy requests to (you can probably tell what my usecase is...)

Field type Description Default
host string The IP address to bind to 0.0.0.0
port integer The (TCP) port to run the HTTP server on 80
domain_names array unimplemented The domain names that the server should respond to, this has also not been implemented yet and does nothing yet []
enable_logging boolean Enable/disable request logging (what gets logged is currently limited and not quite customisable) true
root_dir string This is where your static files and assets are located, for example /var/www/html. This is relative to where the config is located if it is not an absolute path, for example, if your config is located at /Users/name/personal/chimney.toml and the root_dir is set to "public", this will be resolved to /Users/name/personal/public "public"
fallback_document string The file that should be served if the requested path is neither a file that exists nor a valid redirect/rewrite, leaving this blank is also allowed and will just send the status code with no body. A good usecase would be setting this to index.html if you are serving an SPA, or 404.html if you have an Astro site for example "index.html"
https.enable boolean unimplemented false
https.auto_redirect boolean unimplemented false
https.port integer unimplemented 443
https.use_self_signed boolean unimplemented false
https.cert_file string unimplemented nil
https.key_file string unimplemented nil
rewrites table A rewrite generally maintains the same URL but serves something different, the file doesn't even need to exist. A rewrite could in fact point to a redirect, the leading slash is required when defining a rewrite. For example, if you have a rewrite defined as "/foo" = "page.html", even though foo is not a real file, when the server receives a request for /foo, it will read and serve the page.html file instead without the user knowing
headers table Extra headers you want to append to every response the server sends out nil
redirects table A redirect maps a path to an external URL (including the current site). Unlike rewrites, a redirect does not read or serve a file, it simply takes the user away to the specified URL, and replays the request (useful for POSTs) if configured to. For example, "/foo" = { to = "https://example.com", replay = false } will take the user to example.com anytime they visit yourwebsite.com/foo but will NOT replay the request if it was a POST or similar. nil

You can find sample config files here and here.

Why not [this other proxy/server]?

Again, the first point is the major one (and the last) for my usecase. The caddy image is over 1GB (really should not be), the nginx image is still fairly small too at around 25MB, but the reason I did not pick either for my usecase and instead opted into making this is because I:

  • already had a well-defined scope, I only needed a static file server, these other proxies just also happen to be function as file servers, and they work fine but I did not want the 90% of features just to use the 10%
  • wanted a bit more control, not just being able to extend as I go (also very possible with Caddy and Nginx) but things like using TOML and in turn making defining things like redirects and rewrites pretty easy and familiar (I agree too, not much of a good reason)
  • wanted to use and learn Rust properly, obviously, this was a great fit for it!

Contributing & feedback

I would love to hear from people who are actively using this mainly for bug fixes and feature suggestions, I may or may not add your desired feature if it doesn't fit any of the goals.

You might also like...
Sero is a web server that allows you to easily host your static sites without pain. The idea was inspired by surge.sh but gives you full control.

sero Lightning-fast, static web publishing with zero configuration and full control 📖 Table Of Contents 📖 Table Of Contents 🔧 Tools ❓ About The Pro

A opinionated and fast static analyzer for PHP.
A opinionated and fast static analyzer for PHP.

TLDR; A static analyzer for PHP. It helps you catch common mistakes in your PHP code. These are the current checks implemented. Extending undefined cl

A CLI tool for CIs and build scripts, making file system based caching easy and correct (locking, eviction, etc.)

FS Dir Cache A CLI tool for CIs and build scripts, making file system based caching easy and correct (locking, eviction, etc.) When working on build s

Nodium is an easy-to-use data analysis and automation platform built using Rust, designed to be versatile and modular.
Nodium is an easy-to-use data analysis and automation platform built using Rust, designed to be versatile and modular.

Nodium is an easy-to-use data analysis and automation platform built using Rust, designed to be versatile and modular. Nodium aims to provide a user-friendly visual node-based interface for various tasks.

Simple low-level web server to serve file uploads with some shell scripting-friendly features

http_file_uploader Simple low-level web server to serve file uploads with some shell scripting-friendly features. A bridge between Web's multipart/for

Kurzlink is a simple static site generator built in rust

kurzlink What is kurzlink? Kurzlink is a simple static site generator built in rust.

82 fun and easy to use, lightweight, spinners for Rust, with minimal overhead.
82 fun and easy to use, lightweight, spinners for Rust, with minimal overhead.

Spinners for Rust 82 fun and easy to use, lightweight, spinners for Rust, with minimal overhead, all the way from simple dots, to fun emoji based "spi

An easy to use library for pretty print tables of Rust structs and enums.
An easy to use library for pretty print tables of Rust structs and enums.

tabled An easy to use library for pretty printing tables of Rust structs and enums. Table of Contents Usage Settings Style Themes ASCII Psql Github Ma

An easy-to-use SocketCAN library for Python and C++, built in Rust.

JCAN An easy-to-use SocketCAN library for Python and C++, built in Rust, using cxx-rs and pyo3. Warning: I have never used Rust before and I don't kno

Comments
  • Major additions and refactors!

    Major additions and refactors!

    • Flattened folder structure
    • Cleaned up serve_file function
    • Support redirects (#5)
    • Account for nested folders (#7)
    • Added a few unit tests
    • Added GH workflow for testing
    opened by aosasona 0
  • feat: properly set mimetype for other files

    feat: properly set mimetype for other files

    For files like the ones that will live in the .well-known directory, robots.txt, even *.json files and other such files, their mimetype should be properly inferred before falling back to text/html

    urgent 
    opened by aosasona 0
  • feat: implement cache rules

    feat: implement cache rules

    The user should be able to control the default caching duration for specific file formats and paths even. Still unsure what that will look like but this is my current thought:

    [cache_rules]
    "*.png|*.jpg" = { duration = 30, exclude_dir = ["something"] } # where duration is `time to live`  (better term instead of duration) and 30 is in seconds
    "/path/*" = 30 # matches /path/foo, /path/bar etc
    "/exact-path" = 100 # strictly matches /exact-path
    

    In code, extension-based cache rules and path-based cache rules will be handled separately.

    opened by aosasona 0
  • feat: support external SSL/TLS certs

    feat: support external SSL/TLS certs

    • [ ] Users should be able to use something like certbot and then point the server to where those certificates are
    • [ ] Maybe support automatic cert generation via Let's Encrypt or ZeroSSL
    opened by aosasona 0
Releases(0.2.2)
Owner
Ayodeji O.
I like types and I live in Neo(Vim)
Ayodeji O.
A blazing fast and easy to use TRPC-like server for Rust.

rspc ?? Work in progress ?? A blazing fast and easy to use TRPC-like server for Rust. Website Example You define a trpc router and attach resolvers to

Oscar Beaumont 344 Dec 31, 2022
A file server that supports static serving, uploading, searching, accessing control, webdav...

Dufs Dufs is a distinctive utility file server that supports static serving, uploading, searching, accessing control, webdav... Features Serve static

null 3.6k Oct 30, 2023
A simple, fast, and easy to use Solidity test generator based on the Branching Tree Technique.

bulloak A simple, fast, and easy to use Solidity test generator based on the Branching Tree Technique. Installing cargo install bulloak Usage Basic Us

Alexander González 38 Aug 7, 2023
A fast static code analyzer & language server for Python

pylyzer ⚡ pylyzer is a static code analyzer / language server for Python written in Rust. Installation cargo (rust package manager) cargo install pyly

Shunsuke Shibayama 78 Jan 3, 2023
Over-simplified, featherweight, open-source and easy-to-use authentication and authorization server.

concess ⚠️ Early Development: This is not production ready, yet. Do not use it for anything important. Introduction concess is a over-simplified, feat

Dustin Frisch 3 Nov 25, 2022
Yet another lightweight and easy to use HTTP(S) server

Raptor Web server Raptor is a HTTP server written in Rust with aims to use as little memory as possible and an easy configuration. It is built on top

Volham 5 Oct 15, 2022
A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text!

uwuifyy A robust, customizable, blazingly-fast, efficient and easy-to-use command line application to uwu'ify your text! Logo Credits: Jade Nelson Tab

Hamothy 43 Dec 12, 2022
🚀 A blazingly fast easy to use dotfile and global theme manager written in Rust

GTHEME A blazingly fast easy to use dotfile and global theme manager for *NIX systems written in Rust ?? Demo using wip desktop. To check out more des

David Rodriguez 19 Nov 28, 2022
A simple cross-platform easy to use STL Viewer with GUI and CLI options

Stlvi STL viewer written in Rust. This project is still in development. It is available in both CLI and GUI mode. Supported OS Linux Windows Mac Scree

Mantresh Khurana 4 Mar 2, 2023
Minimal and blazing-fast file server. For real, this time.

Zy Minimal and blazing-fast file server. For real, this time. Features Single Page Application support Partial responses (Range support) Cross-Origin

Miraculous Owonubi 17 Dec 18, 2022