DEBOPS.FOODSOFT(5)

NAME
debops.foodsoft - Setup and manage Foodsoft

INTRODUCTION

The debops-contrib.foodsoft role allows to setup your own Foodsoft <https://www.foodcoops.net/> instance. Foodsoft is a web-based software to manage a non-profit food coop (product catalog, ordering, accounting, job scheduling).

The role is based on the following documentation:

•   Deployment (Debian) <https://github.com/foodcoop-adam/foodsoft/wiki/Deployment-%28Debian%29>

•   SETUP_DEVELOPMENT.md <https://github.com/foodcoops/foodsoft/blob/master/doc/SETUP_DEVELOPMENT.md#manual-configuration>

•   Dockerfile <https://github.com/foodcoops/foodsoft/blob/master/Dockerfile>

    Note that the author of this role currently does not have an production deployment using this role but he will try to maintain this role as good as possible. He just wrote this role just for fun to try out Foodsoft.

  Installation

This role requires at least Ansible v2.1.5. To install it, run:

ansible-galaxy install debops-contrib.foodsoft

GETTING STARTED

•   Database support

•   Webserver support

•   Example inventory

•   Example playbook

•   Ansible tags

  Database support

It is recommended that you install a database server. You can install one on the same host as Foodsoft or choose a different host:

[debops_service_mariadb_server]
hostname

In case you chose a different host, you will need to specify which of your database servers the Foodsoft instance should use by specifying the database server host as foodsoft__database_server.

  Webserver support

Currently, only nginx is supported using the debops.nginx role.

You will need to install Nginx with Passenger support by setting:

nginx_flavor: 'passenger'

in your inventory.

  Example inventory

To manage Foodsoft on a given host or set of hosts, they need to be added to the [debops_service_foodsoft_nginx] Ansible group in the inventory:

[debops_service_foodsoft_nginx]
hostname
[debops_service_mariadb_server]
hostname

  Example playbook

Ansible playbook that uses the debops-contrib.foodsoft role together with debops.nginx:

---
- name: Setup and manage Foodsoft with Nginx as webserver
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_foodsoft_nginx' ]
  become: True
  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'
  roles:
    - role: apt_preferences
      tags: [ 'role::apt_preferences' ]
      apt_preferences__dependent_list:
        - '{{ nginx__apt_preferences__dependent_list }}'
    - role: ferm
      tags: [ 'role::ferm', 'skip::ferm' ]
      ferm__dependent_rules:
        - '{{ nginx__ferm__dependent_rules }}'
    - role: mariadb
      tags: [ 'role::mariadb' ]
      mariadb__dependent_databases: '{{ foodsoft__mariadb__dependent_databases }}'
      mariadb__dependent_users: '{{ foodsoft__mariadb__dependent_users }}'
      when: (foodsoft__database == 'mariadb')
    - role: ruby
      tags: [ 'role::ruby' ]
    - role: nginx
      tags: [ 'role::nginx' ]
      nginx__dependent_servers:
        - '{{ foodsoft__nginx__dependent_servers }}'
    - role: foodsoft
      tags: [ 'role::foodsoft' ]

The playbook is shipped with this role under ./docs/playbooks/ from which you can symlink it to your playbook directory.

  Ansible tags

You can use Ansible --tags or --skip-tags parameters to limit what tasks are performed during Ansible run. This can be used after a host was first configured to speed up playbook execution, when you are sure that most of the configuration is already in the desired state.

Available role tags:

role::foodsoft
    Main role tag, should be used in the playbook to execute all of the role tasks as well as role dependencies.

role::foodsoft:pkgs
    Tasks related to system package management like installing or removing packages.

role::foodsoft:config
    Tasks related to configuring Foodsoft.

DEBOPS-CONTRIB.FOODSOFT DEFAULT VARIABLES

  Sections

•   System packages

•   FQDN and DNS addresses

•   Database configuration

•   Webserver configuration

•   Directory paths

•   System user and group

•   Foodsoft sources and deployment

•   Foodsoft configuration

•   Configuration for other Ansible roles

  System packages

foodsoft__base_packages

    List of base packages required by Foodsoft.

    foodsoft__base_packages:
      - '{{ ["ruby2.0", "ruby2.0-dev"] if (ansible_distribution == "Ubuntu" and ansible_distribution_release in ["trusty"]) else [] }}'
      - 'libcurl3-dev'
      - 'libxml2-dev'
      - 'libxslt-dev'
      - 'libffi-dev'
      - 'libreadline-dev'
      ## charlock_holmes
      - 'g++'
      ## https://stackoverflow.com/questions/15553792/error-installing-charlock-holmes-error-installing-gitlab/15556110#15556110
      - 'libicu-dev'
      ## RMagick
      - 'pkg-config'
      - 'libmagickwand-dev'
      - 'ruby-magic'
      - 'libmagic-dev'
      ## sqlite3
      - '{{ ["libsqlite3-dev"] if (foodsoft__database in ["sqlite"]) else [] }}'
      ## mysql2
      - '{{ ["libmysqlclient-dev", "libmariadbd-dev"] if (foodsoft__database in ["mariadb"]) else [] }}'
      ## Install via gem
      # - 'ruby-charlock-holmes'
      # - 'ruby-rmagick'

foodsoft__deploy_state

    What is the desired state which this role should achieve? Possible options:

present
    Default. Ensure that Foodsoft is installed and configured as requested.

absent
    Ensure that Foodsoft is uninstalled and it's configuration is removed.

purged
    Same as absent but additionally also ensures that the database and other persistent data is removed.

    foodsoft__deploy_state: 'present'

  FQDN and DNS addresses

foodsoft__fqdn

    The Fully Qualified Domain Name of the Foodsoft instance. This address is used to configure the webserver frontend.

    foodsoft__fqdn: 'foodsoft.{{ foodsoft__domain }}'

foodsoft__domain

    Domain that will be configured for the Foodsoft instance.

    foodsoft__domain: '{{ ansible_domain }}'

  Database configuration

foodsoft__database

    Autodetected variable containing the database management system which should be used. The supported and tested option is mariadb.

    Refer to Getting started for details.

    foodsoft__database: '{{ ansible_local.foodsoft.database
                            if (ansible_local.foodsoft.database | d())
                            else ("mariadb"
                                  if (ansible_local | d() and ansible_local.mariadb is defined)
                                  else ("postgresql"
                                        if (ansible_local | d() and ansible_local.postgresql is defined)
                                        else "no-database-detected")) }}'

foodsoft__database_server

    FQDN of the database server. It will be configured by the debops.mariadb <https://github.com/debops/ansible-mariadb> or debops.postgresql <https://github.com/debops/ansible-postgresql> role.

    foodsoft__database_server: '{{ ansible_local[foodsoft__database].server }}'

foodsoft__database_port

    Port database is listening on.

    foodsoft__database_port: '{{ ansible_local[foodsoft__database].port }}'

foodsoft__database_name

    Name of the database to use for Foodsoft.

    foodsoft__database_name: 'foodsoft'

foodsoft__database_user

    Database user to use for Foodsoft.

    foodsoft__database_user: 'foodsoft'

foodsoft__database_password_path

    Path to database password file.

    foodsoft__database_password_path: '{{ secret + "/" + foodsoft__database + "/"
                                          + ansible_local[foodsoft__database].delegate_to
                                          + (("/" + ansible_local[foodsoft__database].port)
                                             if (foodsoft__database == "postgresql")
                                             else "")
                                          + "/credentials/" + foodsoft__database_user + "/password" }}'

foodsoft__database_password

    Database password for Foodsoft.

    foodsoft__database_password: '{{ lookup("password", foodsoft__database_password_path + " length=48 chars=ascii_letters,digits,.:-_") }}'

foodsoft__database_name_map

    Database name mapping from the names as used in DebOps to Ruby database adapter names.

    foodsoft__database_name_map:
      'mariadb': 'mysql2'
      'sqlite': 'sqlite3'
      # Legacy:
      'mysql': 'mysql2'

foodsoft__database_config

    Database configuration for Foodsoft. Written to config/database.yml.

    foodsoft__database_config:
      production:
        adapter: '{{ foodsoft__database_name_map[foodsoft__database] }}'
        # socket: '/tmp/mysql.sock'
        host: '{{ foodsoft__database_server }}'
        reconnect: False
        pool: 5
        username: '{{ foodsoft__database_user }}'
        password: '{{ foodsoft__database_password }}'
        database: '{{ foodsoft__database_name }}'
        encoding: 'utf8'

  Webserver configuration

foodsoft__webserver

    Autodetected variable containing the webserver which should be used. Currently only Nginx is supported.

    foodsoft__webserver: '{{ ansible_local.foodsoft.webserver
                             if (ansible_local.foodsoft.webserver | d())
                             else ("nginx"
                                   if (ansible_local.nginx.enabled | d() | bool)
                                   else ("apache"
                                         if (ansible_local.apache.enabled | d() | bool)
                                         else "no-webserver-detected")) }}'

foodsoft__webserver_user

    Name of the webserver user account which will be granted read only access to the Foodsoft application directory.

    foodsoft__webserver_user: '{{ ansible_local.nginx.user | d("www-data") }}'

  Directory paths

foodsoft__home_path

    The Foodsoft system account home directory.

    foodsoft__home_path: '{{ ansible_local.nginx.www | d("/srv/www") + "/" + foodsoft__user }}'

foodsoft__www_path

    Base web root directory for Foodsoft.

    foodsoft__www_path: '{{ foodsoft__git_dest + "/public" }}'

  System user and group

foodsoft__user

    System UNIX account used by the Foodsoft.

    foodsoft__user: 'foodsoft'

foodsoft__group

    System UNIX group used by the Foodsoft.

    foodsoft__group: 'foodsoft'

foodsoft__gecos

    Contents of the GECOS field set for the Foodsoft account.

    foodsoft__gecos: 'Foodsoft'

foodsoft__shell

    The default shell set on the foodsoft account.

    foodsoft__shell: '/usr/sbin/nologin'

  Foodsoft sources and deployment

foodsoft__git_repo

    The URI of the Foodsoft git source repository. There is also https://github.com/foodcoop-adam/foodsoft.git which you can choose alternatively.

    foodsoft__git_repo: 'https://github.com/foodcoops/foodsoft.git'

foodsoft__git_version

    The git branch or tag which will be installed. Defaults to the commit hash of latest release (4.5.1). This is done because Foodsoft development is not cryptographically signed and this role wants to comply with the DebOps Software Source Policy <https://docs.debops.org/en/latest/debops-policy/docs/software-source-policy.html#software-installed-from-git-repositories>.

    foodsoft__git_version: 'a7b6b0c803ca4a79ddab7cea92545b8cc188f952'

foodsoft__git_dest

    Path where the Foodsoft sources will be checked out (installation path).

    foodsoft__git_dest: '{{ foodsoft__home_path + "/foodcoops-foodsoft" }}'

foodsoft__git_update

    Should new revisions be retrieved from the origin repository?

    foodsoft__git_update: True

foodsoft__bundler_exclude_groups

    Don’t install the Gems in the listed groups.

    foodsoft__bundler_exclude_groups:
      - 'test'
      ## Contains SQLite gem.
      - 'development'

  Foodsoft configuration

foodsoft__name

    Name of this Foodsoft instance.

    foodsoft__name: 'Foodcoop'

foodsoft__contact

    Foodcoop contact information (used for FAX messages).

    foodsoft__contact:
      street: 'Grüne Straße 23'
      zip_code: '12323'
      city: 'Berlin'
      country: 'Deutschland'
      email: '{{ foodsoft__email_sender }}'
      phone: '030 323 232323'

foodsoft__default_scope

    If foodsoft__multi_coop_install is true you have to use a coop name, which you you wanna be selected by default.

    foodsoft__default_scope: 'f'

foodsoft__homepage

    Homepage URL.

    foodsoft__homepage: 'https://{{ foodsoft__fqdn }}/{{ foodsoft__default_scope }}'

foodsoft__page_footer

    Page footer (html allowed). Default is a Foodsoft footer. Set to the word "blank" for no footer. If unchanged, the default footer of Foodsoft will be used.

    foodsoft__page_footer: '<a href="{{ foodsoft__homepage }}/">{{ foodsoft__name }}</a>, setup by <a href="https://debops.org/">DebOps</a>.'

foodsoft__email_sender

    Email address to be used as sender.

    foodsoft__email_sender: 'foodsoft@{{ foodsoft__domain }}'

foodsoft__error_recipients

    Email address to be used as sender.

    foodsoft__error_recipients:
      - 'admin@{{ foodsoft__domain }}'

foodsoft__multi_coop_install

    If you wanna serve more than one Foodcoop with one installation. Don't forget to setup databases for each Foodcoop. See also MULTI_COOP_INSTALL.

    foodsoft__multi_coop_install: False

foodsoft__upstream_config

    Configuration as defined by upstream Foodcoop in config/app_config.yml.SAMPLE.

    foodsoft__upstream_config: '{{ lookup("file", "vars/sample_app_config.yml") | from_yaml }}'

foodsoft__role_config

    This dict is managed by the role itself, controlled by other default variables.

    foodsoft__role_config:
      multi_coop_install: '{{ foodsoft__multi_coop_install | bool }}'
      default_scope: '{{ foodsoft__default_scope }}'
      name: '{{ foodsoft__name }}'
      contact: '{{ foodsoft__contact }}'
      homepage: '{{ foodsoft__homepage }}'
      # Default timezone, e. g. UTC, Amsterdam, Berlin, etc.
      # FIXME: Foodsoft/Ruby seem to expect a different format than what debops.core returns.
      # Potentially splitting at "/" and returning the second half of the string
      # would do the job but that would need testing.
      # Change manually if needed.
      # time_zone: '{{ ansible_local.tzdata.timezone | d("Etc/UTC") }}'
      # Page footer (html allowed). Default is a Foodsoft footer. Set to `blank` for no footer.
      page_footer: '{{ foodsoft__page_footer }}'
      email_sender: '{{ foodsoft__email_sender }}'
      # Config for the exception_notification plugin.
      notification:
        error_recipients: '{{ foodsoft__error_recipients }}'
        sender_address: '"Foodsoft Error" <{{ foodsoft__email_sender }}>'
        email_prefix: "[Foodsoft]"

foodsoft__config

    This dict is intended to be used in Ansible’s global inventory as needed.

    foodsoft__config: {}

foodsoft__group_config

    This dict is intended to be used in a host inventory group of Ansible (only one host group is supported) as needed.

    foodsoft__group_config: {}

foodsoft__host_config

    This dict is intended to be used in the inventory of hosts as needed.

    foodsoft__host_config: {}

foodsoft__combined_config

    The configuration written to config/app_config.yml.

    foodsoft__combined_config: '{{ foodsoft__upstream_config.default
                                   | combine(foodsoft__role_config)
                                   | combine(foodsoft__config)
                                   | combine(foodsoft__group_config)
                                   | combine(foodsoft__host_config) }}'

  Configuration for other Ansible roles

foodsoft__mariadb__dependent_databases

    Configuration of the foodsoft database managed by the debops.mariadb <https://github.com/debops/ansible-mariadb> role.

    foodsoft__mariadb__dependent_databases:
      - database: '{{ foodsoft__database_name }}'
        state: '{{ "present" if (foodsoft__deploy_state != "purged") else "absent" }}'

foodsoft__mariadb__dependent_users

    Configuration of the foodsoft database user managed by the debops.mariadb <https://github.com/debops/ansible-mariadb> role.

    foodsoft__mariadb__dependent_users:
      - database: '{{ foodsoft__database_name }}'
        state: '{{ "present" if (foodsoft__deploy_state == "present") else "absent" }}'
        user: '{{ foodsoft__database_user }}'
        password: '{{ foodsoft__database_password }}'

foodsoft__nginx__dependent_servers

    Configuration of the foodsoft nginx server, used by the debops.nginx <https://github.com/debops/ansible-nginx> Ansible role.

    foodsoft__nginx__dependent_servers:
      - name: '{{ foodsoft__fqdn }}'
        filename: 'debops.foodsoft'
        by_role: 'debops-contrib.foodsoft'
        enabled: True
        type: 'rails'
        root: '{{ foodsoft__www_path }}'
        webroot_create: False
        # Foodsoft manages this by itself by default.
        # TODO: Should probably be disabled in Foodsoft so that DebOps can manage it.
        hsts_enabled: False
        frame_options: False
        content_type_options: False
        xss_protection: '{{ omit }}'
        # Phusion Passenger options
        passenger_user: '{{ foodsoft__user }}'
        passenger_group: '{{ foodsoft__group }}'

COPYRIGHT

foodsoft - Setup and manage Foodsoft
Copyright (C) 2015-2017 Robin Schneider <ypid@riseup.net>
Copyright (C) 2016-2017 DebOps <https://debops.org/>
SPDX-License-Identifier: GPL-3.0-only
This Ansible role is part of DebOps.
DebOps is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, as
published by the Free Software Foundation.
DebOps is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DebOps. If not, see https://www.gnu.org/licenses/.

AUTHOR
Robin Schneider

COPYRIGHT
2014-2024, Maciej Delmanowski, Nick Janetakis, Robin Schneider and others