Skip to main content

Tutorial

Overview

This tutorial walks through packaging a web app for Cloudron.

A Cloudron app is a Docker container that runs within the platform's managed environment. The key differences from a standard Docker setup:

  • The filesystem is readonly at runtime. Only /tmp, /run, and /app/data are writable. This prevents code from being overwritten and ensures reliable updates.
  • Databases, caching, and email are provided as addons through environment variables — apps do not manage their own services. Shared resources enable reliable, platform-managed backups.
  • A CloudronManifest.json file declares the app's metadata, port bindings, and addon requirements.

By the end of this tutorial, a working app will be running on Cloudron with a build-install-update development loop.

The steps involved:

  • Create a Dockerfile for the app.
  • Create a CloudronManifest.json declaring addons and metadata.
  • Install the app using cloudron install. The source is uploaded and built on the server.
  • Update the app using cloudron update.

Prerequisites

CLI

The CLI is a command line tool for building and installing custom apps. Install it on your PC/Mac:

sudo npm install -g cloudron

Login to the server:

cloudron login my.example.com
Opening browser for authentication...
Login successful.

Run cloudron --help for a list of all available commands. See CLI docs for a full reference.

Sample app

Several sample repositories are available to get started. Use cloudron init to create a bare bone app, or clone one of the following:

git clone https://git.cloudron.io/docs/tutorial-nodejs-app
git clone https://git.cloudron.io/docs/tutorial-typescript-app
git clone https://git.cloudron.io/docs/tutorial-php-app
git clone https://git.cloudron.io/docs/tutorial-supervisor-app

All published packages are open source and available at git.cloudron.io/packages. Any of these can serve as a starting point.

Install

From the app directory, run cloudron install. The CLI uploads the source directory to the server, which builds the Docker image and starts the app:

# switch to the package dir
cd tutorial-nodejs-app

# install the package
cloudron install
No build detected. This package will be built on the server.
Location: tutorial
App is being installed.

=> Queued .
=> Registering subdomains
=> Registering location tutorial.example.com .......
=> Building image
=> Waiting for propagation of tutorial.example.com ..
=> Wait for health check

App is installed.

The .dockerignore file controls which files are included in the upload. Keep this file up to date to avoid uploading unnecessary files.

Open the app in a browser:

# open the app in the browser
cloudron open

Logs

View the app's log output using cloudron logs. Use cloudron logs -f to follow logs in real time:

cloudron logs
Using cloudron app.example.com
16:44:11 [main] Server running at port 8000

Update

After making changes, run cloudron update from the app directory. The source is uploaded and rebuilt on the server:

# updates app after creating a backup. use --no-backup to skip backup.
$ cloudron update
No docker image detected. Creating source archive from this folder.

=> Waiting for app to be updated
=> Queued .
=> Backup - Uploading app snapshot testapp.example.com
=> Backup - Copying snapshot/app_1d7fca7c-d01c-435f-a228-5a49d34e35e9 to 2026-02-28-145956-737/app_testapp.example.com_v0.1.0 with concurrency of 10
=> Deleting old containers .......
=> Building image
=> Wait for health check ......

App is updated.

Use cloudron install and cloudron update repeatedly during development.

Debugging

Inspecting the filesystem

Use cloudron exec to open a shell inside a running app:

cloudron exec

Repair mode

When an app keeps crashing, cloudron exec may not stay connected. Use cloudron debug for these situations. In debug mode, the app pauses without running the Dockerfile's CMD and the filesystem becomes read-write:

cloudron debug

Disable debug mode with cloudron debug --disable.

Using a container registry

The default cloudron install and cloudron update commands build the app on the server. To offload builds, install the Container registry app and use cloudron builder.

Create an app password in the Container registry, then log in:

cloudron builder login
Registry URL (e.g. https://registry.example.com): https://registry.example.com
Username: username
Password:
Login successful.

Build the image. The CLI remembers the repository name for later runs:

cloudron builder build
Building remotely via https://registry.example.com

Enter repository name (e.g username/org.example.myapp): username/org.example.myapp

Building Dockerfile as registry.example.com/username/org.example.myapp:20260827-144512-a1b2c3d4e via https://registry.example.com
...
Docker image: registry.example.com/username/org.example.myapp:20260827-144512-a1b2c3d4e

Build successful

Run `cloudron install` (or `cloudron update`) to use this image.

Then install or update as usual:

cloudron install

On a terminal, the CLI asks whether to use the last builder image. In CI (no TTY), it uses the last image automatically. cloudron versions add and cloudron appstore upload use the same last image (--last-build skips the prompt; --image records a specific image). On-server installs cannot be published.

Private repositories

Repositories in the Container registry are private by default. Cloudron cannot pull the image until either:

  • the repository is made public in the Container registry, or
  • the registry is added under Private registry using a Container registry app password.

To change the saved repository or start fresh, run cloudron builder reset.

Next steps

The Cheat sheet covers platform-specific considerations for writing the Dockerfile and start script.