Wiki > Nextcloud container new
Nextcloud is a self-hosted platform for syncing and sharing files, calendars and contacts, with apps for the web, desktop and mobile devices.
This article runs the official, community-maintained Nextcloud container image with rootless Podman, alongside PostgreSQL for the database, Redis for caching and file locking, and a second Nextcloud container that runs background jobs. Our Managed Links service provides HTTPS in front of the HTTP-only Nextcloud server.
14144 was randomly generated for this article; you may use any 5-digit port between 10000 and 32767.
Your Nextcloud address will be https://nextcloud.user.box.ca. You create this Managed Link in step 10, once Nextcloud is running, because a link can only be added for a port that is already in use. Name the link nextcloud. If you use a different name, CalDAV/CardDAV (calendars and contacts) may not work, and you will need to replace nextcloud in every nextcloud.user.box.ca address below, including in the Compose file.
Installation
-
Connect to your slot via SSH.
-
Create the folders for Nextcloud and its database:
mkdir -p ~/nextcloud/html ~/nextcloud/db -
Create the database credentials file. This generates a random password, so you don't need to choose or remember one:
printf 'POSTGRES_DB=nextcloud\nPOSTGRES_USER=nextcloud\nPOSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)" > ~/nextcloud/db.env chmod 600 ~/nextcloud/db.env -
Create the file for your Nextcloud admin account:
touch ~/nextcloud/admin.env chmod 600 ~/nextcloud/admin.env nano ~/nextcloud/admin.envPaste in the following, replacing
changemewith a strong, unique password (do not reuse your Whatbox password). Use letters and numbers only. You can change the username too:NEXTCLOUD_ADMIN_USER=user NEXTCLOUD_ADMIN_PASSWORD=changemeSave with
Ctrl + Sand exit withCtrl + X.Setting the admin account here installs Nextcloud automatically on its first start, so nobody else can reach the setup page and claim your instance before you do.
-
Create the Compose file:
nano ~/nextcloud/compose.yaml -
Paste in the following, then save and exit:
x-nextcloud: &nextcloud image: docker.io/library/nextcloud:35-apache restart: unless-stopped env_file: - db.env environment: - POSTGRES_HOST=db - REDIS_HOST=redis - NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.user.box.ca - OVERWRITEHOST=nextcloud.user.box.ca - OVERWRITEPROTOCOL=https - OVERWRITECLIURL=https://nextcloud.user.box.ca - APACHE_DISABLE_REWRITE_IP=1 - TRUSTED_PROXIES=127.0.0.1 volumes: - /home/user/nextcloud/html:/var/www/html depends_on: - db - redis services: db: image: docker.io/library/postgres:18-alpine restart: unless-stopped env_file: - db.env volumes: - /home/user/nextcloud/db:/var/lib/postgresql/18/docker redis: image: docker.io/library/redis:alpine restart: unless-stopped app: <<: *nextcloud env_file: - db.env - admin.env ports: - "127.0.0.1:14144:80" cron: <<: *nextcloud entrypoint: /cron.shThe image versions are pinned on purpose: Nextcloud can only be upgraded one major version at a time, and PostgreSQL can't open data from a different major version. See Updating.
-
Start Nextcloud:
cd ~/nextcloud && podman-compose up -d -
The first start downloads the images, copies Nextcloud into
~/nextcloud/htmland installs it, which takes a few minutes. Follow the progress with:podman logs -f nextcloud_app_1When you see
Nextcloud was successfully installedfollowed by an Apache startup line, pressCtrl + Cto stop following the log. -
Switch background jobs to the
croncontainer:podman exec -u 33 nextcloud_app_1 php occ background:cron -
Create the Managed Link now that Nextcloud is listening on 14144:
- Open your Manage Links page.
- Click Edit Apps, then Add App.
- Enter
nextcloudas the app's name, and14144as the port. - Check Enable websockets, then click Save.
-
Visit https://nextcloud.user.box.ca and log in with the admin account from step 4.
Nextcloud only reads admin.env during installation. You can now remove the NEXTCLOUD_ADMIN_PASSWORD line from it so the password isn't stored in plain text; leave the file itself in place, as the Compose file refers to it.
To connect the desktop and mobile apps, use https://nextcloud.user.box.ca as the server address.
Configuration
Running occ commands
Nextcloud is administered from the command line with occ. It must run inside the app container as the web server user (33):
podman exec -u 33 nextcloud_app_1 php occ <command>
To shorten this to occ <command>, add an alias (skip if you've already done this):
echo "alias occ='podman exec -u 33 nextcloud_app_1 php occ'" >> ~/.bashrc && source ~/.bashrc
The rest of this article uses the full command.
Use occ rather than editing config.php by hand. The image combines several configuration files, so config.php alone doesn't show your real settings; occ config:list system does.
Clearing setup warnings
Administration settings → Overview lists recommended changes. These commands clear the common ones on a new install:
podman exec -u 33 nextcloud_app_1 php occ db:add-missing-indices
podman exec -u 33 nextcloud_app_1 php occ maintenance:repair --include-expensive
podman exec -u 33 nextcloud_app_1 php occ config:system:set maintenance_window_start --type=integer --value=1
podman exec -u 33 nextcloud_app_1 php occ config:system:set default_phone_region --value="CA"
podman exec -u 33 nextcloud_app_1 php occ config:system:set serverid --type=integer --value=1
podman exec -u 33 nextcloud_app_1 php occ app:disable app_api
Replace CA with your country's two-letter code. The last command turns off AppAPI, which runs external apps through a container daemon that isn't available on Whatbox. The warning about email can be ignored.
Upload size
The desktop and mobile apps, and the web interface, upload large files in chunks, so most users never hit a limit. If uploads from other clients, such as WebDAV, fail on large files, raise both PHP's and Apache's limits. Add these lines under environment: in the x-nextcloud block at the top of compose.yaml:
- PHP_UPLOAD_LIMIT=4G
- APACHE_BODY_LIMIT=4294967296
APACHE_BODY_LIMIT is in bytes (4294967296 is 4 GiB). Keep the two values matching.
Then recreate the containers with cd ~/nextcloud && podman-compose down && podman-compose up -d. The same applies to any other setting from the image documentation.
Accessing your Whatbox files (optional)
Nextcloud keeps its own files in ~/nextcloud/html/data. To browse the rest of your slot, such as ~/files, from Nextcloud, connect it over SFTP with a key:
-
Enable the External storage app:
podman exec -u 33 nextcloud_app_1 php occ app:enable files_external -
In Nextcloud, open Administration settings → External storage and add a storage:
- Folder name:
Whatbox(or anything you like) - External storage: SFTP
- Authentication: RSA public key
- Host:
whatbox(this is the name containers use to reach your slot) - Root:
/home/user/files - Username:
user
- Folder name:
-
Set Key size to
4096, click Generate keys, and copy the public key that appears. -
Back in SSH, add the key to your authorized keys, pasting it between the quotes:
mkdir -p ~/.ssh && echo "PASTE-PUBLIC-KEY-HERE" >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys -
A green tick next to the storage means it connected. By default only your account can see it; use Available for to share it with other Nextcloud users.
Automatically Restart (optional)
Rootless containers don't start again by themselves after the server reboots. This script starts any stopped Nextcloud containers.
-
Create a restart script:
touch ~/nextcloud_restart.cron nano -w ~/nextcloud_restart.cron -
Paste in the following:
#!/bin/bash if [ "$(podman ps -q --filter label=io.podman.compose.project=nextcloud --filter status=running | wc -l)" -ge 4 ] then echo "Nextcloud is running." else echo "Nextcloud is not running, starting Nextcloud" podman start nextcloud_db_1 nextcloud_redis_1 nextcloud_app_1 nextcloud_cron_1 fi exitSave and exit.
-
Make the script executable:
chmod +x ~/nextcloud_restart.cron -
Open your crontab:
EDITOR=nano crontab -e -
Add these lines, then save and exit:
@reboot /home/user/nextcloud_restart.cron >/dev/null 2>&1 */5 * * * * /home/user/nextcloud_restart.cron >/dev/null 2>&1
Updating
The browser updater is disabled in the container image. Nextcloud is updated by pulling a newer image instead, and the container upgrades your installation the next time it starts.
Backing up first
Back up before any major upgrade:
podman exec -u 33 nextcloud_app_1 php occ maintenance:mode --on
podman exec nextcloud_db_1 pg_dump -U nextcloud nextcloud > ~/nextcloud-db-$(date +%F).sql
podman unshare tar czf ~/nextcloud-html-$(date +%F).tar.gz -C ~/nextcloud html
podman exec -u 33 nextcloud_app_1 php occ maintenance:mode --off
The second archive includes all your Nextcloud files, so make sure you have room for it.
Minor updates
-
If you set up the restart script, comment out its two lines in your crontab (
EDITOR=nano crontab -e) so it doesn't start containers mid-update. -
Pull the latest images for the pinned versions and recreate the containers:
cd ~/nextcloud podman-compose pull podman-compose down podman-compose up -d -
Watch
podman logs -f nextcloud_app_1until Apache has started, then uncomment the crontab lines.
Major upgrades
Nextcloud can only be upgraded one major version at a time (for example 35 to 36, then 36 to 37). Check that the apps you use support the new version first.
-
Back up as above.
-
Edit
~/nextcloud/compose.yamland change the version in theimage:line at the top, for example fromnextcloud:35-apachetonextcloud:36-apache. Becauseappandcronshare it, this is the only line to change. -
Follow the steps under Minor updates.
-
If the log shows
differs from the latest version of this image, refresh the image's configuration files and restart:podman exec nextcloud_app_1 sh -c "cp /usr/src/nextcloud/config/*.php /var/www/html/config" podman restart nextcloud_app_1 nextcloud_cron_1 -
Run
podman exec -u 33 nextcloud_app_1 php occ db:add-missing-indicesto apply any new database indices.
Leave PostgreSQL at 18-alpine. Moving to a newer PostgreSQL major version requires exporting and re-importing the database, and isn't needed while Nextcloud supports 18. The database folder is mounted at a path that includes the version (/var/lib/postgresql/18/docker), so that path would change too.
Upgrading from the previous version of this article
The previous instructions used unpinned images, a service named nc, a server folder, and passwords written into the Compose file.
-
Check which Nextcloud version you're running, and note your database password from the old
compose.yaml:podman exec -u 33 nextcloud_nc_1 php occ status grep POSTGRES_PASSWORD ~/nextcloud/compose.yaml -
Stop the old containers:
cd ~/nextcloud && podman-compose down -
Rename the Nextcloud folder to match the new layout. The database folder stays where it is:
mv ~/nextcloud/server ~/nextcloud/html -
Create
db.envwith your existing password, not a new one, and an emptyadmin.env:printf 'POSTGRES_DB=nextcloud\nPOSTGRES_USER=nextcloud\nPOSTGRES_PASSWORD=%s\n' "YOUR-OLD-PASSWORD" > ~/nextcloud/db.env touch ~/nextcloud/admin.env chmod 600 ~/nextcloud/db.env ~/nextcloud/admin.env -
Replace
compose.yamlwith the one from step 6 of Installation. Set thenextcloud:tag to the major versionocc statusshowed in step 1 (for example33-apache), not a newer one. -
Start Nextcloud as in steps 7–9 of Installation. If you were on an older major version, upgrade one version at a time as described above until you reach the current one.
Uninstalling
This deletes all files stored in Nextcloud. Download anything you want to keep first. Files on your slot that you reached through External storage are not affected.
Nextcloud's files are owned by the container's users, so they must be deleted through podman unshare.
-
Remove the two
nextcloud_restart.cronlines from your crontab (EDITOR=nano crontab -e). -
Stop and remove the containers, then delete everything:
cd ~/nextcloud && podman-compose down && cd ~ podman unshare rm -rf ~/nextcloud rm -f ~/nextcloud_restart.cron -
Optionally, remove the downloaded images:
podman rmi docker.io/library/nextcloud:35-apache docker.io/library/postgres:18-alpine docker.io/library/redis:alpine -
Delete the
nextcloudapp from your Manage Links page.
Troubleshooting
-
The Managed Link shows an error or "Bad Gateway": Nextcloud isn't running or is still installing. Check
podman ps -aandpodman logs nextcloud_app_1. -
"403 Forbidden" in the browser, or
Could not open input file: occ: the first start was interrupted before Nextcloud was copied into~/nextcloud/html, so later starts skip the installation. On a new install with nothing to lose, start again with empty folders:cd ~/nextcloud && podman-compose down podman unshare rm -rf ~/nextcloud/html ~/nextcloud/db mkdir ~/nextcloud/html ~/nextcloud/db podman-compose up -d -
"Access through untrusted domain": you're using an address other than the one in
NEXTCLOUD_TRUSTED_DOMAINS, or you named the Managed Link something other thannextcloud. Add the address you use:podman exec -u 33 nextcloud_app_1 php occ config:system:set trusted_domains 1 --value=nextcloud.user.box.ca -
"Please use the command line updater because updating via browser is disabled": this is expected. Update by pulling a newer image as described in Updating.
-
"Permission denied" when reading or deleting files in
~/nextcloud: the files belong to the containers' users. Prefix the command withpodman unshare, for examplepodman unshare ls ~/nextcloud/html/data. -
Installation fails with a database authentication error:
db.envchanged after the database was first created. The database keeps its original password. Put the original password back indb.env, or, on a new install with nothing to lose, runpodman-compose down,podman unshare rm -rf ~/nextcloud/db,mkdir ~/nextcloud/dband start again. -
The database container exits after changing the PostgreSQL version: PostgreSQL can't read data from another major version. Set the image back to
postgres:18-alpine. -
Calendar or contacts apps can't find your account: the Managed Link must be named
nextcloud. You can also give the apps the full address: https://nextcloud.user.box.ca/remote.php/dav -
Containers won't stop or start: run
podman-compose downfrom~/nextcloud. If a container is stuck,pkill -f 'conmon.*nextcloud'and try again. -
Anything else: see the Nextcloud Admin Manual and the Nextcloud image documentation, or ask on the Nextcloud forum.