CottonDeployment
Deployment

A serious file cloud should still be simple to run.

Cotton keeps the deployment shape compact: one application image, PostgreSQL, persistent chunk storage, and a setup wizard that turns first-run decisions into product UI.

Install Cotton CloudDockerPostgreSQLFilesystem storageS3 storageSetup wizard

Small runtime surface

Cotton runs as a cohesive ASP.NET Core application instead of a pile of unrelated runtimes. Postgres stores metadata; the chunk store can live on filesystem or S3-compatible storage.

Compose without ceremony

The basic Compose shape is intentionally direct: Postgres, Cotton, a bind mount for /app/files, database connection variables, and no manual Docker network or connection-string ceremony.

Key mode is a deployment choice

New exposed instances can leave COTTON_MASTER_KEY out and unlock in the browser. Trusted home deployments can uncomment the master key line for unattended restarts when that tradeoff is acceptable.

Setup wizard

First-run setup covers admin creation, storage choice, email mode, timezone, and telemetry preference. Basic setup lives in the product instead of hidden environment folklore.

Email modes

Cotton can use Cloud Cotton Mail, custom SMTP, or disabled email. That keeps simple home deployments and public instances from needing the same mail setup.

Storage backends

Filesystem storage uses atomic temp-file moves and capacity reporting. S3-compatible storage can use existence-checked writes behind the same logical chunk model.

Production paths

The same small start can grow into real operation: local testing, home server behind a reverse proxy, public instance with security checkup and admin 2FA, or S3-backed storage when local filesystem capacity is not the right boundary.

Quotas and pressure guard

User quotas and storage pressure checks help public/demo instances avoid uncontrolled growth and prevent filesystem-backed storage from filling the host disk to zero.

Security diagnostics

After deployment, the admin security checkup points at concrete risks such as public account creation, missing 2FA, writable rootfs, seccomp, ptrace, and Docker socket exposure.

Operational surface area

The deployment story is backed by a single application image, PostgreSQL metadata, filesystem or S3-compatible chunk storage, first-run setup, email-mode selection, quota policy, storage pressure checks, and admin security diagnostics.

Small start, real operations

Cotton is easy to start without pretending production operations are fake. The deployment story is compact enough for a home server, but still exposes the knobs that matter when the instance is public.

What Docker does not solve

Docker and Postgres are only the application shape. Public deployments still need TLS, tested backups, key custody, updates, storage monitoring, and host/container hardening that matches the real threat model.

Deployment proof

Small install shape. Serious operator surface.

Cotton is not sold as a black box appliance. It is a focused Docker/Postgres file cloud with explicit choices for storage, unlock behavior, permissions, hardening, backups, and diagnostics.

One app image

The web UI, API, storage pipeline, setup wizard, and background jobs ship as one Cotton runtime.

PostgreSQL metadata

Postgres stores users, layouts, manifests, tokens, settings, and the database state Cotton verifies.

Persistent chunk volume

/app/files must survive container restarts because it holds chunks and the encrypted master-key sentinel.

Reverse proxy friendly

Run Cotton behind your normal TLS edge for public deployments instead of turning the app container into the whole perimeter.

Runtime shape

Two durable things: database and chunk storage.

The deployment boundary is intentionally boring: generate the database password once, keep your Postgres deployment durable, keep /data/cotton durable, put TLS at the edge, and let the setup wizard handle first-run product choices.

docker-compose.yml shape
services:
  postgres:
    image: postgres:18
    restart: always
    environment:
      POSTGRES_DB: cotton
      POSTGRES_USER: cotton
      POSTGRES_PASSWORD: "replace with output of: openssl rand -base64 32"

  cotton:
    image: bvdcode/cotton:latest
    restart: always
    depends_on:
      - postgres
    ports:
      - "8080:8080"
    volumes:
      - /data/cotton:/app/files
    environment:
      COTTON_PG_HOST: postgres
      COTTON_PG_PORT: "5432"
      COTTON_PG_DATABASE: cotton
      COTTON_PG_USERNAME: cotton
      COTTON_PG_PASSWORD: "same value as POSTGRES_PASSWORD"
      COTTON_RESTORE_DATABASE_IF_EMPTY: "true"
      # Optional unattended restarts; otherwise unlock in browser:
      # COTTON_MASTER_KEY: "replace with output of: openssl rand -base64 24"
    security_opt:
      - no-new-privileges:true

Try locally

Use Compose with a bind-mounted files directory, local Postgres, and browser unlock after boot.

Home server

Keep /data/cotton durable, use your reverse proxy for TLS, and decide whether unattended env unlock fits your threat model.

Public instance

Prefer browser unlock, enable 2FA for admins, configure email, and run the security checkup after exposure.

S3-backed storage

Use S3-compatible chunk storage when the filesystem path is not the right durability or capacity boundary.

Browser unlock by default

New instances can start without COTTON_MASTER_KEY and unlock through /unlock, keeping the key out of container environment metadata.

Environment key when it fits

Trusted home deployments can still use COTTON_MASTER_KEY for unattended restarts. Cotton clears it from its own process after derivation.

Non-root runtime path

The official image prepares volume permissions first, then runs the Cotton process as the .NET app user.

Security checkup after install

The admin UI reports concrete hardening signals such as diagnostics, dumpability, seccomp, ptrace, rootfs, Docker socket, and 2FA coverage.

Backup path

Database recovery belongs in the operating model.

Cotton can create PostgreSQL dumps, store backup artifacts through its own chunk pipeline, and attempt restore on an empty database when configured. That is not a replacement for off-box backups; it is a practical recovery layer inside the product.

Start small

The right pitch is simple: Cotton is easy to start, but it does not pretend operations stop at the first container boot.

Operator boundary

Public deployments still need normal operator work: TLS, backups, key storage, updates, storage monitoring, and host/container hardening that matches the actual threat model.

FAQ

Direct answers

What do I need to run Cotton?

Docker, PostgreSQL, and persistent storage for Cotton chunks. The starter Compose example uses a bind mount to /app/files and direct database variables, with TLS handled by your reverse proxy for public deployments.

Do I need a Docker network or a connection string?

No. The simple Compose shape uses service discovery for Postgres and individual COTTON_PG_* variables. No manual Docker network or connection-string ceremony is needed for the starter path.

Can Cotton use object storage?

Yes. Cotton can use S3-compatible storage for chunk objects while keeping the same metadata and storage pipeline above it.

Should I use COTTON_MASTER_KEY?

It depends on the deployment. For a simple trusted home server, an environment key can make unattended restarts practical. For exposed instances, browser unlock keeps the key out of container environment metadata, but you must store the key safely yourself.

Does Cotton handle database recovery?

Cotton can create PostgreSQL dump backups through its storage pipeline and can attempt restore on an empty database when configured. That is useful, but it does not remove the need for off-box backups.