Difficulty running nextcloud dev container in VSCode

I’ve spent several hours trying to get the devcontainer to run in VSCode without much success.

First I couldn’t get it to create a config.php file, so I had to change the permissions of the ./config folder in the repo before starting the dev container.

After this, I was able to access the Nextcloud startup page where it asks me to enter a user/password and select the data folder and database.

I think at this point I’ve already run into problems because according to server/.devcontainer at master · nextcloud/server · GitHub, this step should have been done for me:

On first start the Container installs and configures Nextcloud with the following credentials:

Nextcloud Admin Login

Username: admin
Password: admin

Postgres credentials

Username: postgres
Password: postgres
Database: postgres

But what I’m getting is this page. As you can see, the next issue is that the data folder isn’t writeable.

I tried manually creating the folder - from the root of the repo (outside the dev container) I ran:

mkdir ./data
chmod 0770 ./data
chown www-data:www-data ./data

But I still get the same error saying the the folder isn’t writeable.

I can bypass this screen by doing chmod 777 ./data, however, that just brings me to the next screen where I get:

So I ran chmod -R 0770 ./data again, and now I get a 500 error

Checking the apache error logs I see:

[Wed May 21 13:14:56.649581 2025] [php:error] [pid 1434] [client 172.19.0.1:36388] PHP Fatal error:  Uncaught PDOException: SQLSTATE[HY000] [14] unable to open database file in /var/www/html/3rdparty/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php:43\nStack trace:\n#0 /var/www/html/3rdparty/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php(43): PDO->__construct()\n#1 /var/www/html/3rdparty/doctrine/dbal/src/Connections/PrimaryReadReplicaConnection.php(255): Doctrine\\DBAL\\Driver\\PDO\\SQLite\\Driver->connect()\n#2 /var/www/html/3rdparty/doctrine/dbal/src/Connections/PrimaryReadReplicaConnection.php(192): Doctrine\\DBAL\\Connections\\PrimaryReadReplicaConnection->connectTo()\n#3 /var/www/html/lib/private/DB/Connection.php(245): Doctrine\\DBAL\\Connections\\PrimaryReadReplicaConnection->performConnect()\n#4 /var/www/html/3rdparty/doctrine/dbal/src/Connections/PrimaryReadReplicaConnection.php(236): OC\\DB\\Connection->performConnect()\n#5 /var/www/html/lib/private/DB/Connection.php(396): Doctrine\\DBAL\\Connections\\PrimaryReadReplicaConnection->ensureConnectedToReplica()\n#6 /var/www/html/lib/private/DB/ConnectionAdapter.php(50): OC\\DB\\Connection->executeQuery()\n#7 /var/www/html/lib/private/DB/QueryBuilder/QueryBuilder.php(289): OC\\DB\\ConnectionAdapter->executeQuery()\n#8 /var/www/html/lib/private/AppConfig.php(1225): OC\\DB\\QueryBuilder\\QueryBuilder->executeQuery()\n#9 /var/www/html/lib/private/AppConfig.php(236): OC\\AppConfig->loadConfig()\n#10 /var/www/html/lib/private/AppConfig.php(1676): OC\\AppConfig->searchValues()\n#11 /var/www/html/lib/private/Server.php(607): OC\\AppConfig->getAppInstalledVersions()\n#12 /var/www/html/lib/private/Memcache/Factory.php(112): OC\\Server->OC\\{closure}()\n#13 /var/www/html/lib/private/Memcache/Factory.php(151): OC\\Memcache\\Factory->getGlobalPrefix()\n#14 /var/www/html/lib/private/User/Manager.php(76): OC\\Memcache\\Factory->createDistributed()\n#15 [internal function]: OC\\User\\Manager->__construct()\n#16 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(61): ReflectionClass->newInstanceArgs()\n#17 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(106): OC\\AppFramework\\Utility\\SimpleContainer->buildClass()\n#18 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(124): OC\\AppFramework\\Utility\\SimpleContainer->resolve()\n#19 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#20 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#21 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(175): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#22 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#23 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(118): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#24 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#25 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#26 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#27 /var/www/html/lib/private/Server.php(462): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#28 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\Server->OC\\{closure}()\n#29 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(122): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#30 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#31 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#32 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#33 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(175): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#34 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#35 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(118): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#36 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#37 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#38 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#39 /var/www/html/lib/private/Server.php(783): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#40 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\Server->OC\\{closure}()\n#41 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(122): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#42 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#43 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#44 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#45 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(175): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#46 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#47 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(118): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#48 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#49 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#50 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(74): OC\\ServerContainer->query()\n#51 [internal function]: OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#52 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(61): array_map()\n#53 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(106): OC\\AppFramework\\Utility\\SimpleContainer->buildClass()\n#54 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(124): OC\\AppFramework\\Utility\\SimpleContainer->resolve()\n#55 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#56 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#57 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(175): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#58 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(153): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#59 /var/www/html/3rdparty/pimple/pimple/src/Pimple/Container.php(118): OC\\AppFramework\\Utility\\SimpleContainer->OC\\AppFramework\\Utility\\{closure}()\n#60 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(120): Pimple\\Container->offsetGet()\n#61 /var/www/html/lib/private/ServerContainer.php(154): OC\\AppFramework\\Utility\\SimpleContainer->query()\n#62 /var/www/html/lib/private/AppFramework/Utility/SimpleContainer.php(42): OC\\ServerContainer->query()\n#63 /var/www/html/lib/public/Server.php(37): OC\\AppFramework\\Utility\\SimpleContainer->get()\n#64 /var/www/html/index.php(90): OCP\\Server::get()\n#65 {main}\n\nNext Doctrine\\DBAL\\Driver\\PDO\\Exception: SQLSTATE[HY000] [14] unable to open database file in /var/www/html/3rdparty/doctrine/dbal/src/Driver/PDO/Exception.php:28\nStack trace:\n#0 /var/www/html/3rdparty/doctrine/dbal/src/Driver/PDO/SQLite/Driver.php(50): Doctrine\\DBAL\\Driver\\PDO\\Exception::new()\n#1 /var/www/html/3rdp
[Wed May 21 13:15:35.900318 2025] [core:warn] [pid 31] AH00098: pid file /var/run/apache2/apache2.pid overwritten -- Unclean shutdown of previous Apache run?
[Wed May 21 13:15:35.905631 2025] [mpm_prefork:notice] [pid 31] AH00163: Apache/2.4.58 (Ubuntu) configured -- resuming normal operations
[Wed May 21 13:15:35.905654 2025] [core:notice] [pid 31] AH00094: Command line: '/usr/sbin/apache2'

At this point I’m starting to feel rather lost. More permissions errors?

This sounds very similar to Help with devcontainer (vs-code).

Are you using Windows or Linux as host OS?

1 Like

This looks like the same issue, thanks for sharing.

I did run git submodule update --init somewhere at the start (from the host). I had forgotten that after several hours of debugging!

Are you using Windows or Linux as host OS?

I’m running a basic Ubuntu 22.04 install under WSL. There could be additional issues coming from WSL but I doubt it, I run other dev containers on this setup all the time, and I’ve never made any changes to the default user/groups.

I did see that when I had the data/ folder at 777 so that I could progress past the initial setup screen, Nextcloud created some files inside with owner/group 1001 (as viewed from outside the container). This user/group doesn’t exist on the host. Docker is 999 which is the highest number assigned.

Inside the container, 1001 belongs to an entity called devcontainer:

getent passwd 1001
devcontainer:x:1001:1001::/home/devcontainer:/bin/bash

OK, I was finally able to solve this. The entity 1001 was the key.

I ran this command from inside the container:

sudo chown -R 1001:1001 ./data ./config ./apps

Now I can access the Nextcloud dashboard and installed some apps.

So I think this is what’s required to get the devcontainer running inside VSCode:

  1. Clone the repo
  2. Create these folders at the repo root before starting the dev container: config/, apps/, data/
  3. Now I’m not entirely sure but maybe you can chown to user 1001 from the host before starting the dev container? Otherwise you will need to try to start it, then chown from inside the container when you get server errors.

Although I’m not sure how the git submodule update --init factors in. Maybe there are additional folders that need their owners changed?

Ok, I fear this could be related with the WSL/Windows stuff: the Linux filesystem defines (as you know/found out) that there are permissions and owner id per file/folder. Windows filesystems like NTFS or FAT on the other hand do have a different notion of permission system.

Some folders in WSL are stored in a virtual file system that has a Linux filesystem. This is the most part of the files in WSL. In /mint/xxx, where xxx is c, d, e, … The host filesystem is mapped transparently but this no permission information can be persisted correctly. As you will probably use such a mapped folder to store the NC files (you want you editor in Windows to access them), the permissions might be a bit off.

I am using native Linux thus, I cannot test/evaluate this. But I use WSL at work and the described problem happened to me in similar ways.

@R0Wi, I have found you did quite some work on the devcontainer system in the last years. Do you know if the system should work on Windows/WSL without additional tweaking? Maybe you can shed some light here…

I hope you do not mind being pulled in here.

Chris

Hi together, unfortunately I have no experience with the NC devcontainer on WSL. The contributions I’ve made have been focussing mainly on Github Codespaces. My idea was to automate the NC dev setup in a way that it’s possible to do a one-click deployment on Github itself. I also use the devcontainer in my local environment on Ubuntu without any issues.

The main working directory /var/www/html gets mounted via local mount, which can always cause issues if the host system is not supporting the file system permissions for Linux properly :slight_smile: Of course we could for example adjust the postStart.sh script accordingly if the chown command really fixes the problem?

1 Like

I am going soon on vacation this I have no access to any testing machines. After that (end of June or even July), I might be able to setup a VM or a small win machine to play with it a bit. Unfortunately, this is quite some time until then, sorry. So, if anyone else volunteers to look into this under windows, this might speed up things.

Chris

My feeling is that assuming this is a WSL problem is the wrong track. I’m using WSL2 with Ubuntu 22.04, and the repo is cloned at ~/dev/nextcloud-server.

WSL2 is essentially a VM with some fancy extras, so it’s a full Linux file system with all permissions.

My understanding of how Ubuntu assigns IDs is that when I create new users, they get numbers assigned starting from 1000. So maybe people testing this until now were lucky enough to be logged in as user 1001, which by coincidence matches the devcontainer user inside the dev container? My user id is 1003, which is what’s causing the mismatch here.

services:
  nextclouddev:
    build: .
    volumes:
      - .:/workspace:cached
      - /var/run/docker.sock:/var/run/docker-host.sock
      - ..:/var/www/html # Ownership of the repo on the host is expected to be 1001
    ...

Of course we could for example adjust the [postStart.sh] script accordingly if the chown command really fixes the problem?

I don’t think this would work because the permissions issues are encountered before poststart is reached.

What might work is to modify entrypoint.sh, maybe that happens soon enough:

#!/bin/bash
#
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
#
sudo chown -R devcontainer:devcontainer /var/www/html
sudo service apache2 start

while sleep 1000; do :; done