# App Store and S3 storage

> Run one-click Docker apps such as n8n, Nextcloud or Uptime Kuma behind a domain, deploy ready-made images, and give customers S3-compatible buckets.

Source: https://zopanel.net/docs/apps  
Updated: 2026-10-07

Besides PHP websites, ZoPanel runs applications in Docker containers and can host S3-compatible object storage on the same server. Both are optional components. Install only what you use, because every component uses memory.

## Install Docker

Docker is needed for the App Store, image-based deployments and S3 storage. Install it in one of these ways:

- **App Store → Install Docker**, or
- **Components → Docker** (admin menu), or
- `--with docker` (or `--profile full`) when you run the installer.

ZoPanel configures Docker so that containers stay isolated from the host and from hosting accounts:

- **User namespaces** (`userns-remap`): container user IDs map to a range that no hosting account uses.
- **Local ports only**: containers publish their ports on 127.0.0.1 only. They cannot bypass the firewall, and visitors reach them through the website's nginx with SSL.
- Containers cannot talk to each other directly (inter-container communication is off).
- Each container runs with `no-new-privileges`, a limit of 512 processes and some Linux capabilities removed (`NET_RAW`, `MKNOD`, `AUDIT_WRITE`).
- **Memory and CPU limits** are set for each app (see the table below; 1 CPU each). A customer's container runs inside the customer's own resource group, so the package's limits also apply.
- App data is stored in `/var/lib/zopanel-apps/<instance>/`. Only root and the container can read it. Environment variables are passed through a root-only file, not the command line.
- Container logs are rotated (3 files of 10 MB).

## App Store

**App Store** lists one-click applications. Installing one creates a website for the domain you choose, starts the container, and proxies the domain to it. SSL is issued automatically once the domain points to the server.

| App | Category | Memory limit |
| --- | --- | --- |
| n8n | Workflow automation | 1024 MB |
| Uptime Kuma | Uptime monitoring and status pages | 512 MB |
| Nextcloud | File sync and share, calendar, contacts | 1024 MB |
| Gitea | Lightweight Git hosting | 512 MB |
| Vaultwarden | Bitwarden-compatible password manager | 256 MB |
| Metabase | Business intelligence dashboards | 1536 MB |
| Ghost | Blogs and newsletters (SQLite) | 768 MB |
| Memos | Lightweight notes | 256 MB |
| Open WebUI | AI chat for OpenAI-compatible and Ollama APIs | 2048 MB |
| OpenClaw | AI assistant you talk to from chat apps (needs an LLM API key) | 2048 MB |
| Flowise | Drag-and-drop AI chatbot and agent builder | 1024 MB |
| Excalidraw | Collaborative whiteboard | 256 MB |

Apps that need an API key ask for it during installation. You pay the model provider directly. Apps whose upstream project stopped getting security fixes are no longer offered, but copies already installed can still be managed.

### Install an app

1. Open **App Store** and choose an app.
2. Enter the domain. Administrators also choose the hosting account the app belongs to.
3. Click **Install**. The task log shows the image download and start.
4. Point the domain's A record to the server if you have not already. SSL follows automatically.

Manage an installed app on its website's **Docker** tab. There you can see its status and output, restart it, and use **Update to latest** to pull the newest image. Your data is kept. If the app generates a login token, it is shown under **Login details**.

### App limits for customers

Customers can install apps themselves when their package allows it. Set the limit in **Packages → Docker apps**:

- `0` means no apps.
- Any other number is the maximum number of apps the account can run.
- Each app's memory limit counts toward the package's **RAM (MB)**. An install is refused if it would go over.

Customers can only install apps from the catalog. Custom images are for administrators.

### Custom Docker images

Administrators can run any public image behind a domain with **App Store → Custom Docker image**. Enter the image, the container port, an optional data path and memory. Images outside the catalog are disabled until you turn them on, as root, on the server:

```bash
zopanel ctl feature enable custom-docker
```

This switch can only be changed on the server, not from the web panel. A compromised panel session therefore cannot start arbitrary containers.

## Image-based deployments

A website's **Deploy** tab can also run your own code as a container:

- **Container (Dockerfile)**: ZoPanel builds the Dockerfile in your repository.
- **Ready-made Docker image**: enter a public image such as `nginx:1.27` or `ghcr.io/owner/app:v2`. Pin a tag. The port comes from the `PORT` variable or the image's `EXPOSE`.

Both use the normal deployment pipeline: health check, zero-downtime switch-over and **Rollback** to the last 5 releases. The container listens on 127.0.0.1 only. Both also need `zopanel ctl feature enable custom-docker` on the server.

## S3 object storage

**S3 storage** gives customers Amazon S3-compatible buckets on your server, for images, uploads, media and backup targets. It uses the Garage engine in a container. The engine needs Docker.

### Set it up (administrator)

1. Open **S3 storage** and click **Install**, or install **S3 object storage** in **Components**. Data is stored in `/var/lib/zopanel-storage`.
2. The S3 API listens on 127.0.0.1 only. To use it from outside the server, point a domain's A record to the server and use **Publish on a domain**. ZoPanel creates a reverse-proxy website for it with automatic SSL.
3. Apps then connect to `https://<that domain>` with region `us-east-1`. Turn on **path-style addressing** in the S3 client.

**Uninstall** removes the container. Your data is kept unless you also tick **Also delete all data and buckets**.

### Buckets

Every hosting account can create buckets in **S3 storage → New bucket**:

- Names are 3–63 lowercase letters, digits and hyphens.
- **Each bucket has its own access key that works only for that bucket.** The secret is shown once. If it is lost, use **Rotate key**. The old key stops working at once.
- Each bucket is limited to the account package's disk size. Buckets do not count toward the account's disk quota.
- An account can have up to 10 buckets. Administrators are not limited.
- The free plan includes 1 bucket on the server. Pro removes the limit.

In **Bucket settings** you can set CORS origins for websites that call the bucket directly, and **Delete objects after (days)** for logs or rotating backups. Unfinished uploads are always cleaned after 7 days. **Browse files** lets you upload, download and delete files and create **Share link**s that expire.

### Public buckets

Tick **Public** to let anyone read files without a key, for example images on a website. You can turn it on or off later. When storage is published on a domain, public files are served at:

```text
https://<storage domain>/<bucket>/<file>
```

Private buckets need the key or a share link. Downloads from the panel's file browser are always served as attachments.

The bucket key works with any S3 SDK or plugin, such as WP Offload Media, Laravel's S3 driver or the AWS SDK.
