MASH Nextcloud Non-interactive Installation

The MASH Nextcloud doc says, after running the initial installation, we need to intervene, with a second ansible run to print some credentials, then an interactive cut-and-paste session, then a third ansible run to finish installation:

After installation, follow Nextcloud's setup wizard... choose any username/password for your account... choose PostgreSQL with the credentials you see after running just run-tags print-nextcloud-db-credentials

Once you've fully installed Nextcloud, adjust its default configuration (URL paths, trusted reverse-proxies, etc.) by running: just run-tags adjust-nextcloud-config

But we want to do this non-interactively: Infrastructure as Code. Nextcloud supports Installing from command line. On our server we can run the in-container equivalent of the occ command shown there:

$ sudo docker exec mash-nextcloud-server \
    php occ maintenance:install \
    --database='pgsql' \
    --database-host='mash-postgres:5432' \
    --database-name='nextcloud' \
    --database-user='nextcloud' \
    --database-pass='...' \
    --admin-user='admin' \
    --admin-pass='...'
Nextcloud was successfully installed

The interactive method appears to set trusted_domains “automagically” based on the URL at which we access it. We need to configure it statically instead:

nextcloud_config_additional_parameters:
  - { key: "trusted_domains 1", value: "{{ nextcloud_hostname }}", type: string }

Let's automate this in the MASH playbook.

There are two ways we could run post-install steps: either add them to the systemd config (e.g. with 'ExecStartPost=...' actions), so systemd runs them after starting the service; or else add playbook steps that are run after 'start' tag. The latter is probably more natural, as there is no reason the target system should contain the logic to be able to re-run such steps.

The systemd ExecStartPost way

Advantages: systemd takes care of running this at the appropriate time. This might be helpful to get the ordering right when multiple services have post-install steps and one service depends on another (such as nextcloud depending on postgres).

Disadvantages: the target system should not need to retain knowledge of how to run post-installation steps. This should be the Ansible controller's job.

# added in defaults/main.yml

nextcloud_admin_username: admin
nextcloud_admin_password: ''

nextcloud_config_default_parameters: |
...
      {
        'key': 'trusted_domains 1',
        'value': nextcloud_hostname,
        'type': 'string',
      },
...
# added in templates/systemd/server.service.j2

{# post-install steps; without redis, tmpfs, additional mounts, etc. #}
ExecStartPost=-{{ devture_systemd_docker_base_host_command_docker }} run \
        --rm \
        --name={{ nextcloud_identifier }}-post-install \
        --log-driver=none \
        --network={{ nextcloud_container_network }} \
        {{ ('--network=' ~ postgres_container_network if postgres_enabled and nextcloud_database_hostname == postgres_identifier and nextcloud_container_network != postgres_container_network else '') }} \
        --user={{ nextcloud_uid }}:{{ nextcloud_gid }} \
        --cap-drop=ALL \
        --read-only \
        --mount type=bind,src={{ nextcloud_data_path }},dst=/var/www/html \
        --env-file={{ nextcloud_config_path }}/env \
        {{ nextcloud_container_image_final }} \
        php /var/www/html/occ \
        maintenance:install \
        --database=pgsql \
        --database-host={{ nextcloud_database_hostname }}:{{ nextcloud_database_port }} \
        --database-name={{ nextcloud_database_name }} \
        --database-user={{ nextcloud_database_username }} \
        --database-pass={{ nextcloud_database_password }} \
        --admin-user={{ nextcloud_admin_username }} \
        --admin-pass={{ nextcloud_admin_password }}

The - sign in ExecStartPost=-... means systemd will ignore the error which this command throws on subsequent starts, after it has succeeded once. (It will say “maintenance:install” is not defined.) Unfortunately this also means any error in running it the first time would also be ignored, but then logs should show something.

That gets us as far as having no interactive steps. After the main setup-all,start there is now only one remaining post-install step to run which is adjust-nextcloud-config.

Running this 'occ maintenance:install' from Ansible

Advantages: this is the Ansible controller's job.

Disadvantages: we're going to have to manage the ordering of these steps across dependencies.

- name: "Run occ maintenance:install"
  ansible.builtin.command:
    cmd: >-
      {{ devture_systemd_docker_base_host_command_docker }}
      run
      --rm
      --name={{ nextcloud_identifier }}-post-install
      --network={{ nextcloud_container_network }}
      {% if postgres_enabled and nextcloud_database_hostname == postgres_identifier and nextcloud_container_network != postgres_container_network %}
      --network={{ postgres_container_network }}
      {% endif %}
      --user={{ nextcloud_uid }}:{{ nextcloud_gid }}
      --cap-drop=ALL
      --read-only
      --mount=type=bind,src={{ nextcloud_data_path }},dst=/var/www/html
      --env-file={{ nextcloud_config_path }}/env
      {{ nextcloud_container_image_final }}
      php
      /var/www/html/occ
      maintenance:install
      --database=pgsql
      --database-host={{ nextcloud_database_hostname }}:{{ nextcloud_database_port }}
      --database-name={{ nextcloud_database_name }}
      --database-user={{ nextcloud_database_username }}
      --database-pass={{ nextcloud_database_password }}
      --admin-user={{ nextcloud_initial_admin_username }}
      --admin-pass={{ nextcloud_initial_admin_password }}
  register: result
  # On successful change: 'Nextcloud was successfully installed' in result.stdout
  # To be conservative, report 'changed' for any result other than the known 'already done' error message.
  changed_when: "'Command \"maintenance:install\" is not defined.' not in result.stderr"
  failed_when: "'Command \"maintenance:install\" is not defined.' not in result.stderr and (result.rc != 0 or result.stderr != '')"

Here's my initial commit for MASH nextcloud non-interactive post-install. It requires a nextcloud_initial_admin_password, it runs with the tag post-install-nextcloud (or post-install-all), and it incorporates the previously separate adjust-nextcloud-config step.

That's another Infrastructure as Code solution with no interactive steps. After the main setup-all,start there is now only one remaining post-install step to run which is post-install-nextcloud (or post-install-all).

That's All For Now

That's enough to satisfy my itch, for now.

All settings are now declared non-interactively, including the admin password.

TODO: Ideally we would go on to make the playbook run the post-install steps automatically after install and start.


Filed this proposal as a MASH playbook issue nextcloud: non-interactive post-install completion #283:

This proposal reduces the Nextcloud post-install requirements to a single, non-interactive step.

It replaces the previous print-nextcloud-db-credentials and interactive GUI setup step and adjust-nextcloud-config with a single non-interactive step, invoked with tag post-install-nextcloud (or post-install-all).

In doing so, it also resolves the following issues:

  • #66, #121: problems with interactive installer assets at non-root base path (by removing it)
  • #131: updating the trusted_domains config (by automating it)

It incidentally introduces the idea of a common post-install-all tag. This could be omitted at this time.

Patches (branches):

  • my ansible-role-nextcloud branch (to pull it: cd .../ansible-role-nextcloud && git pull https://lab.trax.im/fork/github/mother-of-all-self-hosting/ansible-role-nextcloud.git julianfoad-nextcloud-post-install)
  • update to docs/services/nextcloud.md (to pull it: cd .../mash-playbook && git pull https://lab.trax.im/fork/github/mother-of-all-self-hosting/mash-playbook.git julianfoad-nextcloud-post-install)

Follow/Feedback/Contact: RSS feed · Fedi follow this blog: @julian​@wrily.foad.me.uk · use the Cactus Comments box above · matrix me · Fedi follow me · email me · julian.foad.me.uk Donate: via Liberapay All posts © Julian Foad and licensed CC-BY-ND except quotes, translations, or where stated otherwise