Putting it on the internet

To reach ThirtyFile from outside your network, put a reverse proxy with HTTPS in front of it.

On this page
  1. Three things to do
  2. Caddy
  3. nginx
  4. Caddy in the same Docker Compose file
  5. Traefik
  6. Before you open it to the world

Three things to do

  1. Start ThirtyFile with THIRTYFILE_SECURE_COOKIE=true and THIRTYFILE_TRUST_PROXY=true. See Settings.
  2. Set up the reverse proxy with one of the examples below.
  3. Enter the public address under Control panel › General › Site URL.
The proxy setting must match your setup. Behind a proxy it has to be true (or the proxy's address when it runs on another computer), otherwise every visitor looks like the same person and one person's wrong passwords lock everybody out. Without a proxy it has to stay false.

When the proxy runs on the same computer, make ThirtyFile reachable only from there: publish the port as -p 127.0.0.1:8080:8080 (in compose.yaml: "127.0.0.1:8080:8080"). Docker's published ports bypass the computer's firewall (ufw and firewalld don't see them), so -p 8080:8080 would leave ThirtyFile reachable without HTTPS from every network the computer is on. When the proxy runs in Docker too, publish no port at all (see below).

Caddy

Caddy gets and renews the certificate by itself.

files.example.com {
    reverse_proxy 127.0.0.1:8080 {
        flush_interval -1
    }
}

nginx

server {
    listen 80;
    server_name files.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name files.example.com;
    # ssl_certificate …; ssl_certificate_key …;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        client_max_body_size 64m;
        proxy_request_buffering off;
        proxy_buffering off;
        proxy_read_timeout 1h;
    }
}

Caddy in the same Docker Compose file

When the proxy runs in Docker too, put both in one compose.yaml. ThirtyFile then publishes no port at all: only Caddy can reach it, over the network Compose creates for the file.

services:
  thirtyfile:
    image: ghcr.io/thirtyfile/thirtyfile:latest
    container_name: thirtyfile
    restart: unless-stopped
    volumes:
      - ./data:/data
      - ./storage:/storage
    environment:
      THIRTYFILE_SECURE_COOKIE: "true"
      THIRTYFILE_TRUST_PROXY: "true"
    read_only: true
    cap_drop: [ALL]
    cap_add: [CHOWN, SETUID, SETGID, DAC_READ_SEARCH]
    security_opt: ["no-new-privileges:true"]

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-data:/data

container_name keeps the name the commands in the other guides use (docker exec thirtyfile …, docker logs thirtyfile), and the last four lines of the service run ThirtyFile with as few privileges as it needs, as the compose.yaml of each release does. The Traefik example below has them too.

And the Caddyfile next to it, which reaches ThirtyFile by its service name:

files.example.com {
    reverse_proxy thirtyfile:8080 {
        flush_interval -1
    }
}

Traefik

With Traefik already running in Docker (with an entry point websecure on port 443 and a certificate resolver letsencrypt), add labels to ThirtyFile and put it on Traefik's network. No port is published.

services:
  thirtyfile:
    image: ghcr.io/thirtyfile/thirtyfile:latest
    container_name: thirtyfile
    restart: unless-stopped
    volumes:
      - ./data:/data
      - ./storage:/storage
    environment:
      THIRTYFILE_SECURE_COOKIE: "true"
      THIRTYFILE_TRUST_PROXY: "true"
    read_only: true
    cap_drop: [ALL]
    cap_add: [CHOWN, SETUID, SETGID, DAC_READ_SEARCH]
    security_opt: ["no-new-privileges:true"]
    networks: [traefik]
    labels:
      traefik.enable: "true"
      traefik.http.routers.thirtyfile.rule: Host(`files.example.com`)
      traefik.http.routers.thirtyfile.entrypoints: websecure
      traefik.http.routers.thirtyfile.tls.certresolver: letsencrypt
      traefik.http.services.thirtyfile.loadbalancer.server.port: "8080"

networks:
  traefik:
    external: true

Traefik streams uploads and downloads and has no body size limit by default, so nothing else is needed.

Before you open it to the world