Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

gosh! Go Share CI

gosh is a simple HTTP file sharing server on which users can upload their files without login or authentication. All files have a maximum lifetime and are then deleted.


  • Standalone HTTP web server, no additional server needed (might be proxied for HTTPS)
  • Supports a FastCGI server instead of HTTP if --listen fcgi:/path/to.sock
  • Store with both files and some metadata
  • Only safe uploader's IP address for legal reasons, anonymous download
  • File and all metadata are automatically deleted after expiration
  • Configurable maximum lifetime and file size for uploads
  • Replace or drop configured MIME types
  • Simple upload both via webpanel or by curl, wget or the like
  • User manual available from the / page
  • Uploads can specify their own shorter lifetime
  • Each upload generates also generates a custom deletion URL
  • Burn after Reading: uploads can be deleted after the first download
  • Client side caching by HTTP headers Last-Modified and If-Modified-Since and HTTP status code 304
  • On Linux there is additional hardening through Landlock and seccomp-bpf
  • On OpenBSD there is additional hardening through pledge and unveil


Generic Installation

Go is required in a recent version; currently 1.17 or later.

git clone
cd gosh

CGO_ENABLED=0 go build -gcflags="all=-N -l" ./cmd/goshd
CGO_ENABLED=0 go build -gcflags="all=-N -l" ./cmd/gosh-query


On a NixOS system one can configure gosh as a module. Have look at the example in contrib/nixos/.

# Example configuration to proxy gosh with nginx with a valid HTTPS certificate.

{ config, pkgs, ... }:
  imports = [ /path/to/contrib/nixos/ ];  # TODO: copy or link the contrib/nixos/default.nix

  services = {
    gosh = {
      enable = true;
      contactMail = "";
      listenAddress = "";

      maxFilesize = "64MiB";
      maxLifetime = "1w";

      mimeMap = [
        { from = "text/html"; to = "text/plain"; }

    nginx = {
      enable = true;

      recommendedGzipSettings = true;
      recommendedOptimisation = true;
      recommendedTlsSettings = true;
      recommendedProxySettings = true;

      virtualHosts."" = {
        enableACME = true;
        forceSSL = true;

        locations."/".proxyPass = "http://${}/";


Start by (cross-) compiling goshd for OpenBSD as described in the generic instructions above.

Afterwards copy the ./contrib/openbsd/goshd-rcd rc.d file to /etc/rc.d/goshd and modify if necessary. You should at least replace by your domain and create the directories below /var/www.

The service can be activated through:

rcctl set goshd flags -max-filesize 64MiB -max-lifetime 3d -contact
rcctl enable goshd
rcctl start goshd

Your /etc/httpd.conf should contain a server block like the following one:

server "" {
  listen on * tls port 443
  tls {
    certificate "/etc/ssl/"
    key "/etc/ssl/private/"

  connection max request body 67108864  # 64M

  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  location "/*" {
    fastcgi socket "/run/gosh.sock"

Don't forget to rcctl reload httpd your configuration changes.



goshd is the web server, as described above.

Usage of ./goshd:
  -contact string
        Contact E-Mail for abuses
  -listen string
        Listen address for the HTTP server (default ":8080")
  -max-filesize string
        Maximum file size in bytes (default "10MiB")
  -max-lifetime string
        Maximum lifetime (default "24h")
  -mimemap string
        MimeMap to substitute/drop MIMEs
  -store string
        Path to the store
        Verbose logging

An example usage could look like this.

./goshd \
  -contact my@email.address \
  -max-filesize 64MiB \
  -max-lifetime 2w \
  -mimemap Mimemap \
  -store /path/to/my/store/dir

The MimeMap file contains both substitutions or drops in each line and could look as follows.

# Replace text/html with text/plain
text/html text/plain

# Drop PNGs, because reasons.
image/png DROP


The store can also be queried offline to get information or delete items. This is gosh-query's job.

Usage of ./gosh-query:
        Delete selection
  -id string
        Query for an ID
  -ip-addr string
        Query for an IP address
  -store string
        Path to the store
        Verbose logging
# Find all uploads from the localhost:
./gosh-query -store /path/to/store -ip-addr ::1

# Show information for upload with ID abcdef
./gosh-query -store /path/to/store -id abcdef

# And delete this one
./gosh-query -store /path/to/store -delete -id abcdef


Files can be submitted via HTTP POST with common tools, e.g., with curl.

# Upload foo.png
curl -F 'file=@foo.png' http://our-server.example/

# Burn after reading:
curl -F 'file=@foo.png' -F 'burn=1' http://our-server.example/

# Set a custom expiry date, e.g., one day:
curl -F 'file=@foo.png' -F 'time=1d' http://our-server.example/

# Or all together:
curl -F 'file=@foo.png' -F 'time=1d' -F 'burn=1' http://our-server.example/

# Print only URL as response:
curl -F 'file=@foo.png' http://our-server.example/?onlyURL

Shell function

Fish, contrib/fish/

A fish-function allow to easily upload a file to the server of your choice which needs to manually edited. With the -b or --burn flags you may decide to burn the file after reading.

Related Work

Of course, there are already similar projects, for example:

There is also darn, a gosh fork which enables server-side file encryption. Back in time, this code was merged into gosh. However, for the sake of simplicity and because I don't like to trust a remote server, this has been removed again.


Authenticationless HTTP file upload server






Contributors 4