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/dataare 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.jsonfile 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.
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.