English
Get started

← All templates · Productivity

Deploy Odoo in one click

Business apps in one: CRM, sales, invoicing, inventory, website, projects and more

A self-hosted alternative to Salesforce, SAP Business One, and NetSuite.

What is Odoo?

Odoo is a suite of open-source business apps that work alone or together as one ERP. A small company runs its CRM and sales pipeline, quotations and invoices, purchases and inventory, manufacturing, projects and timesheets, employees and time off, a point of sale, a website with an online shop, email marketing, events and live chat from the same database, so a won deal becomes an order, a delivery and an invoice without being typed again.

Each app is installed from Odoo's Apps menu when you need it, and every user signs in to the same web interface, with access rights per app. Odoo Community, the free edition, has the apps above; Odoo S.A. sells Odoo Enterprise, which adds full accounting, Studio, Helpdesk, Documents, Sign, Planning, Field Service and Knowledge.

This template runs Odoo Community from Odoo's official image, version 20, with a Postgres 18 database that New project makes beside it, or one of yours that you pick. The database is initialised and the administrator given the email and password you type before Odoo answers anyone; the database manager stays closed, and customers sign up only by invitation. Its email goes through Resend, SendGrid or Amazon SES, whichever you pick in New project, or nowhere until you pick one.

Hosting Odoo on Pethost

  1. You sign in to Pethost with a passkey, GitHub or Google. No machine yet? You pick a plan, and the link waits until it is ready.
  2. New project opens at Odoo. You fill in what it asks for and click Create project: Email, Admin password.
  3. Email is optional: for Odoo to send it, you pick Resend, SendGrid, or Amazon SES in New project and paste in what it gives you.
  4. New project also makes a new database for Odoo, and links it before the app first starts: Postgres (512 MB). Or you pick one of your Postgres databases: Odoo gets a user and a database of its own in it, which the other apps there cannot read, and the apps in it are backed up and restored together.
  5. In a minute or two Odoo is live at its own address with HTTPS. Its secrets are made at random, and its data is in the nightly backup.
  6. It is a project like any other: you or your agent can change it, roll it back or restore it.

Questions about Odoo

Is Odoo free?

Odoo Community is open source under the LGPL-3.0 and free to use for any number of users. Odoo Enterprise is paid per user and adds apps such as full accounting, Studio, Helpdesk and Documents.

Which apps are in Odoo Community?

Among others CRM, Sales, Invoicing, Purchase, Inventory, Manufacturing, Project, Employees, Time Off, Point of Sale, Website, eCommerce, Email Marketing, Events, Surveys, Live Chat and Discuss.

Odoo vs Salesforce: what is the difference?

Salesforce is a CRM sold per user in its own cloud. Odoo's CRM is one app of many: the same database also holds sales, invoicing, inventory and projects, and Odoo Community costs nothing to run.

Can I add modules from the Odoo App Store?

Yes. A module made for Odoo 20 Community is copied into the addons volume, at /mnt/extra-addons in the odoo service; then Update Apps List in Apps, with developer mode on, shows it for installing.

Does Odoo Community have accounting?

It has Invoicing: customer invoices and vendor bills, payments, taxes and the chart of accounts of your country. Full accounting, with bank synchronisation and reconciliation, financial reports and the accountant's tools, is in Odoo Enterprise.

How much memory and disk does Odoo need?

Odoo takes about 150 MB of memory beside its Postgres of 512 MB, more as you install and use apps; attachments take what their files take. New project gives each of its databases the memory the template recommends, unless you change it: Postgres (512 MB). On Pethost the Starter plan is enough for it, with room for other apps beside it.

Odoo Docker Compose file

The template is this compose.yaml and the variables written into the project’s .env as it is created. Pethost runs the file as it is written. The machine writes how the app signs in to its databases there, as it links them. New project writes the email settings picked in it, or leaves them empty when the app sends none.

Containers: odoo (odoo:20).

Databases, each a project of its own: Postgres (512 MB).

Volumes, in the nightly backup: data, addons.

services:
  odoo:
    image: odoo:20
    restart: unless-stopped
    environment:
      PGHOST: ${DATABASE_HOST:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      PGPORT: ${DATABASE_PORT:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      PGUSER: ${DATABASE_USER:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      PGPASSWORD: ${DATABASE_PASSWORD:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      PGDATABASE: ${DATABASE_NAME:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      # Odoo's bus and cron listen on this database: the app's own, as it may reach no other.
      PGDATABASE_SYSTEM: ${DATABASE_NAME:?reload New project to link a Postgres database, or send link_databases with env_prefix DATABASE}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      MASTER_PASSWORD: ${MASTER_PASSWORD}
      # The mail provider picked in New project, by STARTTLS on its port; with none, Odoo sends no
      # mail until an outgoing mail server is added in its settings.
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USER: ${SMTP_USER}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_FROM: ${SMTP_FROM}
    # The configuration is written at every start from the lines above: one database, the
    # database manager closed, the proxy's headers trusted, and a pool within the connections the
    # Postgres part gives. A new database is initialised before Odoo answers anyone, with
    # auth_signup, which turns free sign-up on when it is installed: so it is installed here, and
    # sign-up set to "On invitation" in the step that gives Odoo's administrator, whose login Odoo
    # makes "admin" with the password "admin", the email and password of the fields. A start that
    # finds auth_signup not installed, or the login still "admin", does what an earlier start left
    # undone.
    command:
      - bash
      - -c
      - |
        set -e
        {
          echo "[options]"
          echo "addons_path = /mnt/extra-addons"
          echo "data_dir = /var/lib/odoo"
          echo "http_interface = 0.0.0.0"
          echo "admin_passwd = $$MASTER_PASSWORD"
          echo "db_name = $$PGDATABASE"
          echo "dbfilter = ^$$PGDATABASE\$$"
          echo "list_db = False"
          echo "proxy_mode = True"
          echo "db_maxconn = 24"
          echo "max_cron_threads = 1"
          if [ -n "$$SMTP_HOST" ]; then
            echo "smtp_server = $$SMTP_HOST"
            echo "smtp_port = $$SMTP_PORT"
            echo "smtp_ssl = True"
            echo "smtp_user = $$SMTP_USER"
            echo "smtp_password = $$SMTP_PASSWORD"
            echo "email_from = $$SMTP_FROM"
          fi
        } > /etc/odoo/odoo.conf
        wait-for-psql.py --timeout=120
        installed="select 1 from ir_module_module where name = 'auth_signup' and state = 'installed'"
        if [ -z "$$(psql -tAc "$$installed" 2>/dev/null)" ]; then
          psql -c 'create extension if not exists pg_trgm'
          odoo -d "$$PGDATABASE" -i base,auth_signup --stop-after-init --no-http
        fi
        admin="select u.login from res_users u join ir_model_data d on d.res_id = u.id where d.module = 'base' and d.name = 'user_admin'"
        if [ "$$(psql -tAc "$$admin" 2>/dev/null)" = admin ]; then
          odoo shell -d "$$PGDATABASE" --no-http <<'PYTHON'
        import os
        admin = env.ref('base.user_admin')
        admin.write({'login': os.environ['ADMIN_EMAIL'], 'email': os.environ['ADMIN_EMAIL'], 'password': os.environ['ADMIN_PASSWORD']})
        env['ir.config_parameter'].set_str('auth_signup.invitation_scope', 'b2b')
        env.cr.commit()
        PYTHON
        fi
        exec odoo
    volumes:
      # Attachments, sessions and the files of installed apps.
      - data:/var/lib/odoo
      - addons:/mnt/extra-addons
    healthcheck:
      test: ["CMD", "curl", "-fsS", "-o", "/dev/null", "http://127.0.0.1:8069/web/health"]
      interval: 10s
      timeout: 5s
      retries: 30
      start_period: 300s
volumes:
  data:
  addons:

More in Productivity