Skip to main content

Install

Two files, a folder, and Docker. The setup builder writes both files for you; you download them, run one command, and you're up. No cloning, no building. The hardware bar is modest: see what you need.

Private beta

While Cobblr is in private beta the images are private, so the steps include one docker login. When the images go public that line goes away.

Two ways to start

  • The fast path. Run over plain HTTP and you're using Cobblr in about five minutes. One limitation: scanning from your phone requires HTTPS, so the camera is off until you add it. Adding it later is a two-line edit to the same install; nothing gets redone.
  • Right the first time. If you'd rather never touch it twice, set up Tailscale before you install (roughly 30 minutes if it's new to you), pick Tailscale in the builder instead of HTTP, and you arrive with HTTPS, the phone camera, and remote access on day one.

Both paths are the same two files and the same command. The only difference is the HTTPS choice you make in the builder, and it's never final.

The fast path: install over HTTP

  1. Generate your files. Open the setup builder. Fill in your email, and under the HTTPS choice pick HTTP (no TLS). Set the address to your box's LAN IP and port, like 192.168.1.50:8088. The builder generates every secret for you. Download .env and docker-compose.yml into one folder on the box.

    Back up the encryption key

    The builder makes you confirm you've saved TENANT_CREDS_ENCRYPTION_KEY before the download unlocks. Keep that copy off this box. If you lose it, stored integration credentials can't be recovered.

  2. Bring it up:

    docker login ghcr.io # private beta only; GitHub username + a read token
    docker compose up -d

    Docker pulls the images (a few minutes the first time) and starts them. Nothing builds.

  3. Open it at http://<your-box-ip>:8088 from any device on your network, or at http://localhost:8088 on the box itself. Create your account (signup is open on first run) and look around.

You now have a working instance, with the one limitation from the fork above:

The phone camera requires HTTPS

Browsers only allow the camera (barcode scanning, photos) over HTTPS or on localhost. Scanning works in the browser on the box at localhost:8088, but not from your phone over http://192.168.x.x. It's a browser rule; nothing in Cobblr overrides it. The next section fixes it in place.

Turn on HTTPS

This section is both the upgrade from the fast path and the first stop on the do-it-right path; the steps call out where the two differ. HTTPS is what the phone camera requires, and depending on the option you pick here, secure remote access can come along with it.

The catch with a home box: a public certificate authority won't issue a certificate for a private IP, and a public name won't reach your box unless you open a port to the internet or run your own DNS. So getting real HTTPS onto your LAN takes one of the approaches below.

We suggest Tailscale. If you don't already have it (or another solution to this problem), it's worth the roughly 30 minutes to set up. It gives you a real certificate with nothing exposed, and as a bonus you can then reach any of your self-hosted things securely from anywhere, not just Cobblr.

Tailscale puts your devices on a private mesh network and hands each one a real, auto-renewed ts.net certificate. Nothing is forwarded, nothing is exposed, and the same URL works at home or away.

  1. Put the box on your tailnet, if it isn't already:

    curl -fsSL https://tailscale.com/install.sh | sh
    sudo tailscale up

    Note the box's name from tailscale status or the admin console. It looks like myserver.tail1234.ts.net.

  2. Point Cobblr at it.

    • Fresh install (the do-it-right path): in the builder, put the ts.net name in the address, pick Tailscale, and bring the files up as in fast-path step 2. Don't expect a page yet: the app stays bound to the box until the next step serves it on the tailnet.
    • Upgrading from the fast path: edit the .env you already have (keep your existing secrets; a fresh builder run would generate new ones, and a new database password or encryption key breaks the running install). Set the address to the ts.net name and remove the WEB_BIND=0.0.0.0 line so the app is reachable only through the tailnet:
      COBBLR_SITE_ADDRESS=myserver.tail1234.ts.net
      COMPOSE_PROFILES=
      Then docker compose up -d.
  3. Serve it with a real certificate:

    sudo tailscale serve --bg 8088
  4. Install Tailscale on your phone and laptop, sign them into the same tailnet, and open the ts.net URL. The camera works everywhere now.

To reach it from outside your tailnet without forwarding a port, use sudo tailscale funnel --bg 8088 instead. Turn signup off first; Funnel must be enabled in your tailnet's ACL policy and serves only on ports 443, 8443, and 10000.

One box, many services?

tailscale serve publishes under the machine's own tailnet name, so the URL is the box's identity (rename the box cobblr in the admin console if you want cobblr.tail1234.ts.net this way). If the box runs several services and you want each on its own service-named hostname, the pattern is Caddy with the tsnet plugin, which joins the tailnet as a virtual node per service. That's outside this guide's scope.

DuckDNS (a free public name)

DuckDNS gives you a free name.duckdns.org and a real Let's Encrypt certificate through a DNS challenge, so the box never opens port 80 for the certificate. To actually reach the box, the name points at your public IP and you forward TCP 443 on your router to the box. That puts the instance on the internet, so set PUBLIC_SIGNUP_ENABLED=false and rely on login.

In the builder pick DuckDNS, claim the name at duckdns.org, and paste its token. This sets COBBLR_TLS_MODE=duckdns and DUCKDNS_TOKEN.

To stay off the internet instead of forwarding a port, add a local DNS entry on your router or Pi-hole mapping the name to the box's LAN IP. Do not point the public DuckDNS record itself at a private IP: DuckDNS keeps resetting it to your public address, and many routers block public names that resolve to private ones.

Cloudflare (your own domain)

If you own a domain on Cloudflare, choose Cloudflare in the builder and paste an API token scoped Zone → DNS → Edit for your zone. It works the same way as DuckDNS but with your own domain: a real certificate through a DNS challenge, with a record like cobblr.example.com pointed at your box and a port forwarded to reach it. This sets COBBLR_TLS_MODE=cloudflare and CLOUDFLARE_API_TOKEN. The local-DNS option applies here too if you'd rather not expose it.

Offline CA (no domain, no internet, no tailnet)

Choose Offline CA in the builder (COBBLR_TLS_MODE=internal). Caddy runs its own certificate authority and issues the certificate locally, so nothing leaves the box. The cost is trusting that CA once per device. After the stack is up, export the CA:

docker compose exec caddy cat /data/caddy/pki/authorities/local/root.crt > cobblr-root.crt

On iOS, install the profile and enable full trust under Settings → General → About → Certificate Trust Settings. On Android, use Settings → Security → Install a certificate → CA certificate. This is the only path that needs no network and no third party at all.

Updating

docker compose pull && docker compose up -d. Details, backups, and troubleshooting are in Operating.

Once you're in, Your first hour picks up inside the app.