How to: Caddy Fileserver

created (updated in this commit)


This tutorial covers how to setup a fileserver for downloading. It does not cover how to upload files, setup WebDAV, or anything else. After following these steps you should have an HTTPS enabled webserver, serving one directory and it’s children.


For this tutorial a Linux server is recommended. For trying it out any platform that can run Docker containers should be fine though. (Sorry, M1 users)


Get Docker & docker-compose

First off, let’s install Docker and docker-compose. Since a lot of distributions do not ship Docker in their repositories, this may require some additional steps, which you can find on the Docker website (see the sidebar for the various distributions, or click in the table)

I recommend consulting your distributions wiki if you run into issues.

Prepare your directories

Choose where you want your containers and data to be. I personally like /container/[name] but you can choose whatever.

Inside this directory create a docker-compose.yml with our service definition:

version: '3'

  caddy:                   # let's call our service something intuitive
    image: 'caddy:alpine'  # use the latest alpine version of caddy
      - "80:80"            # expose port 80, so browsers can be redirected to HTTPS
      - "443:443"          # expose port 443, so browsers can connect securely
    volumes:               # these are the files and directories we want to keep between restarts
      - "./webroot:/srv"
      - "./caddy/Caddyfile:/etc/caddy/Caddyfile"
      - "./caddy/data:/data"
      - "./caddy/config:/config"

Next create the directories we use as volumes. Since on linux there is no advantage in using volumes over bind mounts. If you’re reading this how-to the difference between those two probably doesn’t concern you too much.

mkdir -p webroot caddy/{data,config}

Configure Caddy

What do we want Caddy to do for us? We want:

  1. to serve files
  2. to serve a website we might have
  3. we want a filelist if there is no website
  4. we want a SSL certificate
    • why do we want SSL? because it’s not 2005 anymore1

For this we need to create Caddy’s configuration: the Caddyfile. Open caddy/Caddyfile in your editor of choice and add this configuration: {        # change this to your domain
    file_server browse { # serve files and list them if no index.html is present
        index index.html # if this file is available, show it instead of the
    	                 #     directory listing
        root /srv        # set the entrypoint of your webserver to /srv
    	                 #     if you take a look at the docker-compose.yml
    	                 #     you'll see that this maps to ./webroot

Remember to set your domain, otherwise you will run into errors.

Start everything

Now we just need to run docker compose up -d2 and Docker will automatically download everything we need and start it right away.

How to perform updates

“Installing” updates is made extremely easy: just download the newest version using docker compose pull and recreate the container using docker compose up -d. You’re now running the latest version.


If you run into any problems while following this tutorial, please reach out so I can improve this tutorial. It’s actually not that easy to write a beginner-friendly tutorial if most of the pitfalls are clear to you. You can find the comment Inbox by clicking the link under the footnotes.

  1. I know, quite a thing to say when you look at this website, but it’s intended to only look old, not be old. ↩︎

  2. Since at the time of writing, a lot of distributions haven’t upgraded docker-compose yet, you may need to run docker-compose up -d instead. ↩︎

Do you know better? Have a comment? Great! Let me know by sending an email to ~mpldr/

If you feel like it, you can Liberapay receiving, or GitHub Sponsors.
Unless stated otherwise the texts of this website are released under CC-BY and code-snippets are released into the public domain.
© Moritz Poldrack

RSS Feed available I am sponsoring the letter @. Yes, that's a thing. This website's content doesn't need AI to be stupid! Website Status