Install TinyCld
TinyCld is one Docker container. You run it on any Linux server with Docker installed; it can get an HTTPS certificate from Let’s Encrypt automatically (opt-in), stores its data in a single directory, and updates with docker compose pull && docker compose up -d.
The actual install is the same on every host:
mkdir tinycld && cd tinycld
curl -O https://raw.githubusercontent.com/tinycld/tinycld/main/docker-compose.yml
# edit docker-compose.yml: set PRIMARY_DOMAIN, and AUTOCERT_ENABLED: "true" for HTTPS
docker compose up -d
What changes between hosting providers is how you get the server itself. The sections below walk through the recommended providers. If you already have a Linux box with Docker, skip to On your own server.
Before you start
You need:
- A domain name - TinyCld uses it to get an HTTPS certificate. Any domain works. If you don’t have one, register a cheap
.comor.xyzat a registrar like Porkbun or Cloudflare (~$10/year). - 15 minutes.
You do not need:
- A PaaS account, a deploy platform, a build step. The image is published to GitHub Container Registry; you pull it, you run it.
- Kubernetes. When autocert is enabled (
AUTOCERT_ENABLED: "true"+PRIMARY_DOMAIN), TinyCld terminates TLS itself via Let’s Encrypt and binds:80/:443directly — no reverse proxy needed. Without autocert it serves plain HTTP on:7090, which is what you’d put behind your own NGINX/Caddy/Cloudflare if you prefer.
What the container needs
- 1 CPU, 2 GB RAM is comfortable for a small team. 1 GB works if it’s just you.
- 20 GB disk to start. The image itself is ~600 MB compressed (~2.5 GB on disk, since it bundles the Go toolchain and Node runtime for the in-app package installer). Email and file uploads add up; plan to grow.
- Ports 80 and 443 open to the internet, when running with
AUTOCERT_ENABLED: "true"+PRIMARY_DOMAINset. 80 is required for the Let’s Encrypt ACME challenge; you cannot skip it. - Port 7090 for plain-HTTP mode (autocert off — local demos or behind an external reverse proxy). Remap the host side to any port you like in
docker-compose.yml. - Ports 993 and 465 if you’re running the mail package. If
dovecot/postfixare already on the host using these ports, comment those mappings out ofdocker-compose.ymlor remap them. - Persistent storage - the
pb_data/directory on the host. Back it up.
On your own server
If you already have a Linux VM with Docker and a domain pointed at it:
mkdir tinycld && cd tinycld
curl -O https://raw.githubusercontent.com/tinycld/tinycld/main/docker-compose.yml
Open docker-compose.yml in your editor. To get HTTPS automatically via Let’s Encrypt, set both:
environment:
PRIMARY_DOMAIN: "tinycld.example.com"
AUTOCERT_ENABLED: "true"
If you’d rather run plain HTTP on :7090 (local demo, or behind your own reverse proxy), leave AUTOCERT_ENABLED unset and set PRIMARY_DOMAIN so the printed setup URL still points at your real host.
Start it:
docker compose up -d
docker compose logs -f
Once the container’s listening, visit https://tinycld.example.com/setup (or http://<host>:7090/setup in plain-HTTP mode). Jump to First-run setup.
Recommended providers
Each of these runs Docker well and has first-party guides for getting the engine installed on Ubuntu. Follow their setup, then return here and jump to On your own server.
Hetzner
Cheapest serious hosting in the world right now. A CX22 (2 vCPU, 4 GB RAM, 40 GB disk) is about €4/month and comfortably handles TinyCld for a small team. No ingress/egress charges up to 20 TB/month. US and EU data centers priced identically.
tinycld.org itself runs on a Hetzner CPX11 (2 vCPU AMD, 2 GB RAM, 40 GB disk, ~€4.35/month) and handles the marketing site, docs, and a demo instance without breaking a sweat.
Setup guide: Docker CE on Hetzner Cloud.
DigitalOcean
The most familiar dashboard for VPS newcomers. A $6/month Basic Droplet handles TinyCld well.
Setup guide: Docker hosting on DigitalOcean.
Linode (Akamai)
Notably patient support for beginners. The $5/month Nanode handles a solo TinyCld install fine; bump to $10/month for a team.
Setup guide: Docker guides on Linode Marketplace.
After the Docker engine is up
Whichever provider you picked, once you have a Linux VM with Docker installed and your domain’s A record pointed at its public IP, the rest is identical:
- SSH into the VM.
- Follow On your own server.
Other providers
TinyCld runs on any Linux host with Docker 20.10+. Providers not covered above that also work fine:
- Vultr - similar to DigitalOcean pricing-wise; $6/month compute plans.
- Hetzner Storage Box or OVH VPS - cheap, reliable for European users.
- Scaleway - French provider with per-second billing.
- Fly.io - platform-as-a-service, works but you’ll need to mount a Fly volume at
/app/pb_dataand override the entrypoint. Harder than a plain VPS. - AWS Lightsail - closest AWS has to a simple VPS. $5/month plans exist.
- Bare metal or home lab - works perfectly if you can port-forward 80 and 443.
The process is always the same: get a Linux machine with a public IP, install Docker, add a DNS A record, run the compose file.
First-run setup
Once the container is running and your domain resolves, visit https://<your-domain>/setup. On first boot there’s no admin account yet, so TinyCld generates a one-time setup token and prints it to the container logs:
docker compose logs tinycld | grep -A 5 'First run'
You’ll see something like:
┌──────────────────────────────────────────────────────────────┐
│ First run setup, visit below URL to configure tinycld: │
│ │
│ https://tinycld.example.com/setup?token=a1b2c3d4e5f6... │
└──────────────────────────────────────────────────────────────┘
Open the URL with the token. The wizard collects four fields:
| Field | Default | Description |
|---|---|---|
| Application name | tinycld | Shows in emails and the admin UI. |
| - | Your superuser account email. | |
| Password | - | Your superuser account password. |
| App URL | Current origin | The public URL, used in outgoing links. |
After submitting, you’re logged in as the superuser and land on the setup dashboard. Create your first organization, add packages, and you’re done.
Updates and backups
Updating
cd tinycld
docker compose pull
docker compose up -d
The container restarts in place. Downtime is typically under ten seconds. Migrations run automatically on boot.
Backups
The entire state is in pb_data/ — the database, file uploads, and the server’s private keys. (Files offloaded to S3 are the exception: they live in your bucket, not pb_data/, so back those up on the bucket side.)
The safest snapshot is PocketBase’s built-in backup: Dashboard → Settings → Backups, where you can take one on demand or set an automatic schedule. It briefly puts the app in read-only mode while it writes a ZIP, so the snapshot is always consistent and there’s no downtime. Backups can also be stored directly in S3-compatible storage. See API Backups to drive it from a script.
A plain tarball also works, but only when the container is stopped — copying pb_data/ while it runs can grab the database mid-write because of SQLite’s write-ahead log. A nightly cron that quiesces first:
0 3 * * * cd /root/tinycld && docker compose stop && tar -czf "/root/backups/tinycld-$(date +\%F).tgz" pb_data/ && docker compose start
This incurs a few seconds of downtime each night. If that’s not acceptable, use the built-in scheduled backup above instead. Either way, ship the archives off-site (rsync, rclone to S3/B2/Backblaze, or a managed backup tool). PocketBase’s Going to production guide covers backup strategy in more depth.
Restoring
Stop the container, replace pb_data/, restart:
docker compose down
rm -rf pb_data
tar -xzf tinycld-2026-04-20.tgz
docker compose up -d
Next steps
- Getting started - orient yourself in the admin dashboard once you’re logged in.
- Adding a package - install mail, contacts, calendar, drive.
- Troubleshooting - common issues.