CottonInstallation guide
Installation guide

Install Cotton Cloud without turning deployment into folklore.

Cotton is a self-hosted file cloud, so installing it is less about memorizing commands and more about understanding the small set of pieces that must stay healthy: the app, the database, the file storage, the domain, HTTPS, and backups.

Install Cotton CloudDockerPostgreSQLVPSHome serverReverse proxy

What you are actually installing

Cotton is the application people open in the browser. PostgreSQL stores the file tree, accounts, shares, settings, and metadata. The real file bytes live in Cotton's chunk storage on a filesystem path or an S3-compatible backend.

  • The application container serves the web UI and API.
  • PostgreSQL keeps structured metadata and should be backed up.
  • Chunk storage keeps the encrypted file content and needs persistent capacity.

The pieces you need before the first command

A clean install starts with choosing where Cotton will live and how people will reach it. The same idea works on a home server, mini PC, NAS-like box, or VPS, but public installs need more discipline around HTTPS and backups.

  • A server that stays online and has enough disk for the files you expect.
  • Docker and Docker Compose to run the Cotton and PostgreSQL containers.
  • A persistent folder or S3-compatible bucket for Cotton file chunks.
  • A domain name and HTTPS endpoint if the instance is reachable from the internet.

Docker in plain language

Docker is the packaging and launch format. Instead of installing runtime pieces by hand on the host, Docker starts Cotton from an image with the expected application environment. Compose is the recipe that says which containers run together and which folders survive restarts.

  • You do not need to write application code to use Docker.
  • You do need to understand which folders are persistent.
  • Deleting the wrong database or storage volume is still data loss.

Choose where Cotton will live

For testing, a local machine is fine. For real use, pick a host that can stay online and be backed up. A laptop that sleeps is a bad server; a small home server or VPS is usually a better starting point.

  • Home server: good for private LAN-first storage and full hardware control.
  • VPS: easier public access, easier DNS and HTTPS, but less physical control.
  • NAS-like host: good when storage capacity matters more than public reach.

Decide where file bytes will live

Cotton can store chunks on a filesystem path or use S3-compatible storage. Filesystem storage is the simplest path when the server owns the disk. S3-compatible storage is useful when capacity, durability, or separate storage operations matter more.

Domain and HTTPS

If Cotton is public, put it behind a reverse proxy and serve it over HTTPS. DNS points a name to the server, the reverse proxy receives web traffic, and TLS keeps browser traffic encrypted in transit.

  • Local-only installs can start without a public domain.
  • Public installs should use HTTPS from the beginning.
  • The reverse proxy is also where you normally handle ports 80 and 443.

First run happens in the browser

After the containers are running, Cotton's setup wizard handles the product decisions: admin account, storage choice, email mode, timezone, telemetry preference, and key mode. That keeps the first install understandable instead of hiding everything in environment variables.

After installation

The install is not finished just because the login page loads. Enable strong admin authentication, check the admin security diagnostics, confirm backups, and make sure you know how to update the containers without losing the database or chunk storage.

  • Enable passkeys or TOTP for the admin account.
  • Verify database and chunk-storage backups outside the server.
  • Run the admin security checkup before exposing the instance widely.

What a good install leaves behind

A good Cotton install leaves you with a reachable HTTPS site, a known PostgreSQL database, a known persistent chunk store, an admin account protected by stronger auth, a backup path, and a clear update routine.

Install the system, not just the container

The practical goal is not to make Docker print a success line. The goal is a file cloud you can reach, update, back up, secure, and explain later when something has to move or be restored.

What not to skip

Do not skip backups, key custody, HTTPS, or persistent storage just because the first container start worked. Those are not advanced extras; they are the line between a demo and a file cloud you can trust.

Step by step

From an empty server to a running Cotton Cloud.

The page above explains the moving parts. This is the actual order of operations: prepare the host, start two containers, finish setup in the browser, then lock it down. Roughly fifteen minutes on a server you already have.

What you need

The minimum before the first command.

Four things that have to be in place before any of the steps make sense.

A server that stays on

A home server, mini PC, NAS-like box, or VPS with enough disk for the files you expect.

Docker and Compose

Docker Engine with the Compose plugin. Everything below runs as two containers.

A persistent path

A directory like /data/cotton that survives restarts. It holds chunks and the encrypted key sentinel.

Domain and TLS (public)

For access from the internet, a domain plus a reverse proxy that terminates HTTPS. Local-only installs can skip this at first.

The install

Six steps, in order.

Each step is short. Keep the order: data, containers, browser, then defense.

1. Prepare the host

Install Docker and the Compose plugin, then create the storage directory: mkdir -p /data/cotton. This is where Cotton keeps file chunks.

2. Generate a database password

Create one strong secret and reuse it for Postgres and Cotton. Do not leave a default password on an exposed instance.

3. Write docker-compose.yml

Paste the compose below, replace the password placeholders, and save it next to your storage path.

4. Start the stack

Run docker compose up -d, then watch the logs until Cotton reports it is listening on port 8080.

5. Finish in the browser

Open the instance and complete the setup wizard: admin account, storage, email, timezone, telemetry, and key mode.

6. Put it behind HTTPS and lock it down

For public access, route your domain through the reverse proxy on 80/443, then run the post-install checklist.

docker-compose.yml

Two containers: Postgres and Cotton.

This is the same compose shape from the deployment page. Replace both password placeholders with the secret you generated, keep /data/cotton durable, and put TLS at your reverse proxy.

docker-compose.yml
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
Run it

Four commands, start to finish.

From an empty directory to first-run logs. Run them on the host where Cotton will live.

shell
# 1. create the storage directory
mkdir -p /data/cotton

# 2. generate one strong database password
openssl rand -base64 32

# 3. start Postgres and Cotton
docker compose up -d

# 4. follow first-run logs
docker compose logs -f cotton
First run

What the setup wizard asks.

Product decisions live in the UI instead of hidden environment folklore.

Admin account

Create the first administrator. This account owns the instance, so protect it immediately after.

Storage choice

Filesystem path or S3-compatible backend for file chunks. Filesystem is the simplest first install.

Email mode

Cloud Cotton Mail, your own SMTP, or email disabled. Public instances usually want working email.

Timezone

Set the instance timezone so timestamps, schedules, and logs read correctly.

Telemetry preference

Set your telemetry preference. Cotton's telemetry is opt-in, so you decide during setup.

Key mode

Browser unlock keeps the master key out of the container, or set COTTON_MASTER_KEY for unattended restarts. Pick the tradeoff that fits.

After install

Do these before you trust it.

The login page loading is not the finish line.

Turn on 2FA

Enable passkeys or TOTP for the admin account before the instance is reachable from outside.

Run the security checkup

The admin checkup flags public signup, missing 2FA, writable rootfs, Docker socket exposure, and more.

Back up off-box

Verify Postgres and chunk-storage backups land somewhere other than the same server.

Know your update path

Confirm how you pull a new image and restart without losing the database or chunk storage.

FAQ

Direct answers

Do I need to understand Docker before installing Cotton?

You do not need to be a Docker expert, but you should understand three things: containers run the app, volumes keep data across restarts, and deleting the wrong volume can delete real data.

Can I install Cotton on a home server?

Yes. A home server, mini PC, or NAS-like machine can work well when it stays online, has enough storage, and has a backup plan. Public access still needs HTTPS and a reverse proxy.

Do I need a domain name?

For local-only testing, no. For a public instance, use a domain and HTTPS so browsers, mobile clients, and desktop clients have one stable secure address.

Why does Cotton need PostgreSQL?

PostgreSQL stores structured metadata: accounts, folders, file records, shares, settings, and operational state. The large file content is stored separately as Cotton chunks.

Where are the actual files?

Cotton stores file content as chunks in the configured storage backend. That backend can be a persistent filesystem path or S3-compatible storage.