1. Home
  2. Docs
  3. Infrastructure
  4. ERPNext
  5. Install ERPNext on Ubuntu VM with Graviton2 (experimental)

Install ERPNext on Ubuntu VM with Graviton2 (experimental)

Installing ERPNext on Kubernetes has advantages in scalability, stability, and elasticity. However, installing on a VM can also be beneficial:

  • easier debugging with “ad-hoc” techniques
  • potential use of AWS Arm Graviton2 instances (too many issues, Frappe will not support it)
  • remote debugging using Code Server or Gitpod

Install ERPNext version-13 and Create a Site using Easy Install Script

References:

Note: This will install MariaDB locally, which is OK. Later you can dump & restore the data from local MariaDB to AWS MariaDB, then purge the local MariaDB installation.

  1. [If you install with Pulumi and/or use Lightsail User Data to do initial update] Wait until apt-get -y full-upgrade completes:
    sudo ps -ef | grep apt
    Make sure there is no apt* running.
  2. Install Prerequisites to run Easy Install Script.
# python3-minimal and python3-setuptools already installed by ubuntu 20.04
sudo apt-get -y install python3-minimal build-essential python3-setuptools

Warning: Unsupported configuration: In Arm 64-bit, these Python packages will need to be built from source, and the needed devel packages:

  • psycopg2 <- libpq-dev & libssl-dev
  • pandas
  • pycountry
# workaround for aarch64
sudo apt-get -y install libpq-dev libssl-dev

2. Inside /home/ubuntu, download Bench’s Easy Install script, apply our fixes, then execute it. The following command will install requirements, install bench, initialize frappe-bench folder and install frappe app version-13-beta, install erpnext app version-13-beta, and create a site named site1.local with ERPNext.

wget https://raw.githubusercontent.com/frappe/bench/develop/install.py
# apply: https://github.com/frappe/bench/pull/1079
# apply: https://github.com/frappe/bench/pull/1086
# apply: https://github.com/frappe/bench/pull/1085
# apply: 
sudo python3 install.py --production --user frappe --version 13 --frappe-branch version-13-beta --erpnext-branch version-13-beta

If you want to install the first site a manually, use --without-site. Note: –without-site is buggy (PR #1087), it still runs Ansible task setup_erpnext.yml:13 & 17.

If you want development environment, replace --production with --develop but make sure to put --user frappe, otherwise it will install bench using the current user.

Logs are saved under /tmp/logs/easy-install__*.log

ubuntu@ip-172-30-0-15:~$ sudo python3 install.py --develop --version 13 --frappe-branch version-13-beta --erpnext-branch version-13-beta --without-site
Logs are saved under /tmp/logs/easy-install__2020-10-03__19-23.log
curl already installed!
wget already installed!
git already installed!
pip3 already installed!
pip3 already installed!
Checking System Compatibility...
ubuntu 20 is compatible!
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
Input MySQL and Frappe Administrator passwords:
Passwords saved at ~/passwords.txt
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[WARNING]: Consider using the get_url or uri module rather than running 'curl'.  If you need to use command because get_url or uri is
insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
[WARNING]: Consider using the file module with owner rather than running 'chown'.  If you need to use command because file is insufficient
you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
[WARNING]: Module remote_tmp /home/ubuntu/.ansible/tmp did not exist and was created with a mode of 0700, this may cause issues when running
as another user. To avoid this, create the remote_tmp dir with the correct permissions manually
Bench + Frappe + ERPNext has been successfully installed!

Excluding troubleshooting & errors, it will take about 60 minutes to complete on m6g.medium Singapore. If you use –develop, you’ll need to run bench start. If you use –production, it will setup supervisor and runs it on port 8000. Now you can access it on http://0.0.0.0:80/.

The resulting /home/frappe folder structure is:

Easy Install using –production:

  • sets up swap.
  • It installs these servers/system packages: ansible, MariaDB, nginx, redis, supervisor. It then uses bench setup * to setup configuration for these components.
  • Optional: bench setup can also generate systemd configuration.

If you didn’t want to create site site1.local, drop it by:

bench drop-site --force site1.local

AWS Application Load Balancer and SSL

Note: bench setup can configure lets-encrypt with nginx.

To support SSL, you can use AWS Application Load Balancer, which supports multiple certificates on the same HTTPS listener using SNI.

For security groups, make sure that both the ALB and your EC2 instance belong to “default” security group so the ALB can access the EC2 instance.

Troubleshooting 2: FAILED Install wkhtmltox deb

TASK [wkhtmltopdf : Install wkhtmltox deb] *************************************
task path: /tmp/.bench/bench/playbooks/roles/wkhtmltopdf/tasks/main.yml:96
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167 `" && echo ansible-tmp-1601708293.7612886-120792339495167="` echo /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167 `" ) && sleep 0'
Using module file /usr/local/lib/python3.8/dist-packages/ansible/modules/packaging/os/apt.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-5126037eujhc7/tmpwmjiuj0t TO /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167/AnsiballZ_apt.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167/ /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167/AnsiballZ_apt.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167/AnsiballZ_apt.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1601708293.7612886-120792339495167/ > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_unauthenticated": false,
            "autoclean": false,
            "autoremove": false,
            "cache_valid_time": 0,
            "deb": "/tmp/wkhtmltox.deb",
            "default_release": null,
            "dpkg_options": "force-confdef,force-confold",
            "force": false,
            "force_apt_get": false,
            "install_recommends": null,
            "only_upgrade": false,
            "package": null,
            "policy_rc_d": null,
            "purge": false,
            "state": "present",
            "update_cache": null,
            "upgrade": null
        }
and update afterwards"
}

RUNNING HANDLER [mariadb : restart mysql] **************************************
task path: /tmp/.bench/bench/playbooks/roles/mariadb/handlers/main.yml:2

PLAY RECAP *********************************************************************
localhost                  : ok=42   changed=28   unreachable=0    failed=1    skipped=42   rescued=0    ignored=0   

Traceback (most recent call last):
  File "install.py", line 472, in <module>
    install_bench(args)
  File "install.py", line 264, in install_bench
    run_playbook('site.yml', sudo=True, extra_vars=extra_vars)
  File "install.py", line 388, in run_playbook
    success = subprocess.check_call(args, cwd=playbooks_folder, stdout=log_stream, stderr=sys.stderr)
  File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ansible-playbook', '-c', 'local', 'site.yml', '-vvvv', '-e', '@/tmp/extra_vars.json', '--become', '--become-user=frappe']' returned non-zero exit status 2.

This was caused by Ansible Playbook /tmp/.bench/bench/playbooks/roles/wkhtmltopdf/tasks/main.yml:96 not supporting Arm64 architecture, although wkhtmltox does. The relevant fact is ansible_architecture, which may contain commonly used x86_64 and aarch64 (Arm 64-bit).

Workaround: https://github.com/frappe/bench/pull/1077

Before retrying, you must remove the cached /tmp/wkhtmltox.deb.

Troubleshooting 3: psycopg2

TASK [bench : Get the ERPNext app] **************************************************************************************************************************************************************
task path: /tmp/.bench/bench/playbooks/roles/bench/tasks/setup_erpnext.yml:6
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/tmp/ansible-tmp-1601717080.3634918-151556251948040 `" && echo ansible-tmp-1601717080.3634918-151556251948040="` echo /var/tmp/ansible-tmp-1601717080.3634918-151556251948040 `" ) && sleep 0'
Using module file /usr/local/lib/python3.8/dist-packages/ansible/modules/commands/command.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-1157571tv4kh8n/tmpswwex2cs TO /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/AnsiballZ_command.py
<127.0.0.1> EXEC /bin/sh -c 'setfacl -m u:frappe:r-x /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/ /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/ /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'chown frappe /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/ /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'sudo -H -S -n  -u frappe /bin/sh -c '"'"'echo BECOME-SUCCESS-ifopudjsiwkunzhvpxgiumghpppzxugn ; /usr/bin/python3 /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/AnsiballZ_command.py'"'"' && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /var/tmp/ansible-tmp-1601717080.3634918-151556251948040/ > /dev/null 2>&1 && sleep 0'
fatal: [localhost]: FAILED! => {
    "changed": true,
    "cmd": [
        "bench",
        "get-app",
        "erpnext",
        "https://github.com/frappe/erpnext",
        "--branch",
        "version-13-beta"
    ],
    "delta": "0:00:00.450672",
    "end": "2020-10-03 09:24:40.958728",
    "invocation": {
        "module_args": {
            "_raw_params": "bench get-app erpnext https://github.com/frappe/erpnext --branch version-13-beta",
            "_uses_shell": false,
            "argv": null,
            "chdir": "/home/frappe/frappe-bench",
            "creates": "/home/frappe/frappe-bench/apps/erpnext",
            "executable": null,
            "removes": null,
            "stdin": null,
            "stdin_add_newline": true,
            "strip_empty_ends": true,
            "warn": true
        }
    },
    "msg": "non-zero return code",
    "rc": 1,
    "start": "2020-10-03 09:24:40.508056",
    "stderr": "Traceback (most recent call last):\n  File \"/usr/local/bin/bench\", line 33, in <module>\n    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())\n  File \"/home/frappe/.bench/bench/cli.py\", line 48, in cli\n    if sys.argv[1] in get_frappe_commands() + [\"--site\", \"--verbose\", \"--force\", \"--profile\"]:\nTypeError: unsupported operand type(s) for +: 'NoneType' and 'list'",
    "stderr_lines": [
        "Traceback (most recent call last):",
        "  File \"/usr/local/bin/bench\", line 33, in <module>",
        "    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())",
        "  File \"/home/frappe/.bench/bench/cli.py\", line 48, in cli",
        "    if sys.argv[1] in get_frappe_commands() + [\"--site\", \"--verbose\", \"--force\", \"--profile\"]:",
        "TypeError: unsupported operand type(s) for +: 'NoneType' and 'list'"
    ],
    "stdout": "\u001b[93mWARN: bench is installed in editable mode!\n\nThis is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`\n\u001b[0m\n/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')",
    "stdout_lines": [
        "\u001b[93mWARN: bench is installed in editable mode!",
        "",
        "This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`",
        "\u001b[0m",
        "/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')"
    ]
}

PLAY RECAP **************************************************************************************************************************************************************************************
localhost                  : ok=72   changed=15   unreachable=0    failed=1    skipped=65   rescued=0    ignored=0   

Traceback (most recent call last):
  File "install.py", line 475, in <module>
    install_bench(args)
  File "install.py", line 264, in install_bench
    run_playbook('site.yml', sudo=True, extra_vars=extra_vars)
  File "install.py", line 388, in run_playbook
    success = subprocess.check_call(args, cwd=playbooks_folder, stdout=log_stream, stderr=sys.stderr)
  File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ansible-playbook', '-c', 'local', 'site.yml', '-vvvv', '-e', '@/tmp/extra_vars.json', '--become', '--become-user=frappe']' returned non-zero exit status 2.

The “WARN: bench is installed in editable mode!” is because bench was modified (to install wkhtmltox).

Key error here is:

TypeError: unsupported operand type(s) for +: ‘NoneType’ and ‘list’

caused by get_frappe_commands() returning None.

You can check by running command directly:

ubuntu@ip-172-30-0-218:~$ sudo -H -u frappe bash
frappe@ip-172-30-0-218:~$ cd /home/frappe/frappe-bench
frappe@ip-172-30-0-218:~/frappe-bench$ ls
apps  config  env  logs  patches.txt  Procfile  sites
frappe@ip-172-30-0-218:~/frappe-bench$ bench get-app erpnext https://github.com/frappe/erpnext --branch version-13-beta
WARN: bench is installed in editable mode!

This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`

/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')

Traceback (most recent call last):
  File "/usr/local/bin/bench", line 33, in <module>
    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())
  File "/home/frappe/.bench/bench/cli.py", line 48, in cli
    if sys.argv[1] in get_frappe_commands() + ["--site", "--verbose", "--force", "--profile"]:
TypeError: unsupported operand type(s) for +: 'NoneType' and 'list'

And get_frappe_commands() calls generate_command_cache() which returned None, due to:

/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for ‘frappe.utils.bench_helper’ (ModuleNotFoundError: No module named ‘frappe’)

This is clear if we raise exception there: (apply PR #1080)

frappe@ip-172-30-0-218:~/frappe-bench$ bench get-app erpnext https://github.com/frappe/erpnext --branch version-13-beta
WARN: bench is installed in editable mode!

This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`

/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')

Traceback (most recent call last):
  File "/usr/local/bin/bench", line 33, in <module>
    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())
  File "/home/frappe/.bench/bench/cli.py", line 48, in cli
    if sys.argv[1] in (get_frappe_commands() + ["--site", "--verbose", "--force", "--profile"]):
  File "/home/frappe/.bench/bench/cli.py", line 138, in get_frappe_commands
    print('get_frappe_commands from generate_command_cache()', generate_command_cache())
  File "/home/frappe/.bench/bench/utils.py", line 1065, in generate_command_cache
    raise e
  File "/home/frappe/.bench/bench/utils.py", line 1056, in generate_command_cache
    output = get_cmd_output("{0} -m frappe.utils.bench_helper get-frappe-commands".format(python), cwd=sites_path)
  File "/home/frappe/.bench/bench/utils.py", line 517, in get_cmd_output
    output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE).strip()
  File "/usr/lib/python3.8/subprocess.py", line 411, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.8/subprocess.py", line 512, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '/home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper get-frappe-commands' returned non-zero exit status 1.

This happened because somehow installation of frappe-bench/apps/frappe failed. Manually, it can be fixed by running:

env/bin/pip install -q  -e ./apps/frappe

Then you’ll see why:

ERROR: Could not install packages due to an EnvironmentError: [Errno 28] No space left on device

Complete steps for resize: (you don’t have to stop your instance, all of these steps can be done “online”, meaning root partition still in use)

  1. Using EC2 Management Console, resize the EBS volume.
  2. sudo growpart /dev/nvme0n1 1
  3. sudo resize2fs /dev/nvme0n1p1

Coming back to “env/bin/pip install -q -e ./apps/frappe”.

Seems like something was wrong during bench/playbooks/roles/bench/tasks/main.yml on “python3 bench init for develop/production”:

  - name:  python3 bench init for develop
    command: bench init {{ bench_path }} --frappe-path {{ frappe_repo_url }} --frappe-branch {{ frappe_branch }} --python {{ python }}
    args:
      creates: "{{ bench_path }}"
    when: not bench_stat.stat.exists and not production

  - name: python3 bench init for production
    command: bench init {{ bench_path }} --frappe-path {{ frappe_repo_url }} --frappe-branch {{ frappe_branch }} --python {{ python }}
    args:
      creates: "{{ bench_path }}"
    when: not bench_stat.stat.exists and production

Indeed, it was error but it still continued as “SUCCESS: Bench /home/frappe/frappe-bench initialized”:

TASK [bench : python3 bench init for production] **********************************************
task path: /tmp/.bench/bench/playbooks/roles/bench/tasks/main.yml:44
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /var/tmp/ansible-tmp-1601721146.1329048-274988510500381 `" && echo ansible-tmp-1601721146.1329048-274988510500381="` echo /var/tmp/ansible-tmp-1601721146.1329048-274988510500381 `" ) && sleep 0'
Using module file /usr/local/lib/python3.8/dist-packages/ansible/modules/commands/command.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-127420pzzo5w2k/tmp2a5zbnl6 TO /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/AnsiballZ_command.py
<127.0.0.1> EXEC /bin/sh -c 'setfacl -m u:frappe:r-x /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/ /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/ /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'chown frappe /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/ /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/AnsiballZ_command.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'sudo -H -S -n  -u frappe /bin/sh -c '"'"'echo BECOME-SUCCESS-qsuzucpjzcvuvwppxbpoxggfsquehqsl ; /usr/bin/python3 /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/AnsiballZ_command.py'"'"' && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /var/tmp/ansible-tmp-1601721146.1329048-274988510500381/ > /dev/null 2>&1 && sleep 0'
changed: [localhost] => {
    "changed": true,
    "cmd": [
        "bench",
        "init",
        "/home/frappe/frappe-bench",
        "--frappe-path",
        "https://github.com/frappe/frappe",
        "--frappe-branch",
        "version-13-beta",
        "--python",
        "python3"
    ],
    "delta": "0:04:03.608667",
    "end": "2020-10-03 10:36:29.885712",
    "invocation": {
        "module_args": {
            "_raw_params": "bench init /home/frappe/frappe-bench --frappe-path https://github.com/frappe/frappe --frappe-branch version-13-beta --python python3",
            "_uses_shell": false,
            "argv": null,
            "chdir": null,
            "creates": "/home/frappe/frappe-bench",
            "executable": null,
            "removes": null,
            "stdin": null,
            "stdin_add_newline": true,
            "strip_empty_ends": true,
            "warn": true
        }
    },
    "rc": 0,
    "start": "2020-10-03 10:32:26.277045",
    "stderr": "Cloning into 'frappe'...\n    ERROR: Command errored out with exit status 1:\n     command: /home/frappe/frappe-bench/env/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '\"'\"'/tmp/pip-install-xcd8afkr/psycopg2-binary/setup.py'\"'\"'; __file__='\"'\"'/tmp/pip-install-xcd8afkr/psycopg2-binary/setup.py'\"'\"';f=getattr(tokenize, '\"'\"'open'\"'\"', open)(__file__);code=f.read().replace('\"'\"'\\r\\n'\"'\"', '\"'\"'\\n'\"'\"');f.close();exec(compile(code, __file__, '\"'\"'exec'\"'\"'))' egg_info --egg-base /tmp/pip-pip-egg-info-juk5kakg\n         cwd: /tmp/pip-install-xcd8afkr/psycopg2-binary/\n    Complete output (23 lines):\n    running egg_info\n    creating /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info\n    writing /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/PKG-INFO\n    writing dependency_links to /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/dependency_links.txt\n    writing top-level names to /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/top_level.txt\n    writing manifest file '/tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/SOURCES.txt'\n    \n    Error: pg_config executable not found.\n    \n    pg_config is required to build psycopg2 from source.  Please add the directory\n    containing pg_config to the $PATH or specify the full executable path with the\n    option:\n    \n        python setup.py build_ext --pg-config /path/to/pg_config build ...\n    \n    or with the pg_config option in 'setup.cfg'.\n    \n    If you prefer to avoid building psycopg2 from source, please install the PyPI\n    'psycopg2-binary' package instead.\n    \n    For further information please check the 'doc/src/install.rst' file (also at\n    <http://initd.org/psycopg/docs/install.html>).\n    \n    ----------------------------------------\nERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.\nwarning \" > [email protected]\" has unmet peer dependency \"[email protected] - 3\".\nwarning \" > [email protected]\" has unmet peer dependency \"popper.js@^1.16.0\".\nTraceback (most recent call last):\n  File \"/usr/local/bin/bench\", line 33, in <module>\n    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())\n  File \"/home/frappe/.bench/bench/cli.py\", line 48, in cli\n    if sys.argv[1] in (get_frappe_commands() + [\"--site\", \"--verbose\", \"--force\", \"--profile\"]):\n  File \"/home/frappe/.bench/bench/cli.py\", line 138, in get_frappe_commands\n    print('get_frappe_commands from generate_command_cache()', generate_command_cache())\n  File \"/home/frappe/.bench/bench/utils.py\", line 1067, in generate_command_cache\n    raise e\n  File \"/home/frappe/.bench/bench/utils.py\", line 1058, in generate_command_cache\n    output = get_cmd_output(command, cwd=sites_path)\n  File \"/home/frappe/.bench/bench/utils.py\", line 517, in get_cmd_output\n    output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE).strip()\n  File \"/usr/lib/python3.8/subprocess.py\", line 411, in check_output\n    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,\n  File \"/usr/lib/python3.8/subprocess.py\", line 512, in run\n    raise CalledProcessError(retcode, process.args,\nsubprocess.CalledProcessError: Command '/home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper get-frappe-commands' returned non-zero exit status 1.",
    "stderr_lines": [
        "Cloning into 'frappe'...",
        "    ERROR: Command errored out with exit status 1:",
        "     command: /home/frappe/frappe-bench/env/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '\"'\"'/tmp/pip-install-xcd8afkr/psycopg2-binary/setup.py'\"'\"'; __file__='\"'\"'/tmp/pip-install-xcd8afkr/psycopg2-binary/setup.py'\"'\"';f=getattr(tokenize, '\"'\"'open'\"'\"', open)(__file__);code=f.read().replace('\"'\"'\\r\\n'\"'\"', '\"'\"'\\n'\"'\"');f.close();exec(compile(code, __file__, '\"'\"'exec'\"'\"'))' egg_info --egg-base /tmp/pip-pip-egg-info-juk5kakg",
        "         cwd: /tmp/pip-install-xcd8afkr/psycopg2-binary/",
        "    Complete output (23 lines):",
        "    running egg_info",
        "    creating /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info",
        "    writing /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/PKG-INFO",
        "    writing dependency_links to /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/dependency_links.txt",
        "    writing top-level names to /tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/top_level.txt",
        "    writing manifest file '/tmp/pip-pip-egg-info-juk5kakg/psycopg2_binary.egg-info/SOURCES.txt'",
        "    ",
        "    Error: pg_config executable not found.",
        "    ",
        "    pg_config is required to build psycopg2 from source.  Please add the directory",
        "    containing pg_config to the $PATH or specify the full executable path with the",
        "    option:",
        "    ",
        "        python setup.py build_ext --pg-config /path/to/pg_config build ...",
        "    ",
        "    or with the pg_config option in 'setup.cfg'.",
        "    ",
        "    If you prefer to avoid building psycopg2 from source, please install the PyPI",
        "    'psycopg2-binary' package instead.",
        "    ",
        "    For further information please check the 'doc/src/install.rst' file (also at",
        "    <http://initd.org/psycopg/docs/install.html>).",
        "    ",
        "    ----------------------------------------",
        "ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.",
        "warning \" > [email protected]\" has unmet peer dependency \"[email protected] - 3\".",
        "warning \" > [email protected]\" has unmet peer dependency \"popper.js@^1.16.0\".",
        "Traceback (most recent call last):",
        "  File \"/usr/local/bin/bench\", line 33, in <module>",
        "    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())",
        "  File \"/home/frappe/.bench/bench/cli.py\", line 48, in cli",
        "    if sys.argv[1] in (get_frappe_commands() + [\"--site\", \"--verbose\", \"--force\", \"--profile\"]):",
        "  File \"/home/frappe/.bench/bench/cli.py\", line 138, in get_frappe_commands",
        "    print('get_frappe_commands from generate_command_cache()', generate_command_cache())",
        "  File \"/home/frappe/.bench/bench/utils.py\", line 1067, in generate_command_cache",
        "    raise e",
        "  File \"/home/frappe/.bench/bench/utils.py\", line 1058, in generate_command_cache",
        "    output = get_cmd_output(command, cwd=sites_path)",
        "  File \"/home/frappe/.bench/bench/utils.py\", line 517, in get_cmd_output",
        "    output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE).strip()",
        "  File \"/usr/lib/python3.8/subprocess.py\", line 411, in check_output",
        "    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,",
        "  File \"/usr/lib/python3.8/subprocess.py\", line 512, in run",
        "    raise CalledProcessError(retcode, process.args,",
        "subprocess.CalledProcessError: Command '/home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper get-frappe-commands' returned non-zero exit status 1."
    ],
    "stdout": "yarn install v1.22.10\n[1/4] Resolving packages...\n[2/4] Fetching packages...\n[3/4] Linking dependencies...\n[4/4] Building fresh packages...\n$ yarn run snyk-protect\nyarn run v1.22.10\n$ snyk protect\nSuccessfully applied Snyk patches\n\nDone in 9.65s.\nDone in 217.85s.\nyarn install v1.22.10\n[1/4] Resolving packages...\nsuccess Already up-to-date.\n$ yarn run snyk-protect\nyarn run v1.22.10\n$ snyk protect\nSuccessfully applied Snyk patches\n\nDone in 3.56s.\nDone in 4.49s.\n\u001b[93mWARN: bench is installed in editable mode!\n\nThis is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`\n\u001b[0m\n/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')\n\n\u001b[93mWARN: bench is installed in editable mode!\n\nThis is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`\n\u001b[0m\nget_frappe_commands returned []\n\u001b[90m$ /usr/local/bin/virtualenv -q env -p python3\u001b[0m\n\n\u001b[93mGetting frappe\u001b[0m\n\u001b[90m$ git clone https://github.com/frappe/frappe --branch version-13-beta --depth 1 --origin upstream\u001b[0m\n\n\u001b[93mInstalling frappe\u001b[0m\n\u001b[90m$ /home/frappe/frappe-bench/env/bin/pip install -q -U -e /home/frappe/frappe-bench/apps/frappe \u001b[0m\n\u001b[90m$ yarn install\u001b[0m\nUpdating node packages...\n\n\u001b[93mInstalling node dependencies for frappe\u001b[0m\n\u001b[90m$ yarn install\u001b[0m\n\u001b[90m$ bench build\u001b[0m\n\u001b[92mSUCCESS: Bench /home/frappe/frappe-bench initialized\u001b[0m",
    "stdout_lines": [
        "yarn install v1.22.10",
        "[1/4] Resolving packages...",
        "[2/4] Fetching packages...",
        "[3/4] Linking dependencies...",
        "[4/4] Building fresh packages...",
        "$ yarn run snyk-protect",
        "yarn run v1.22.10",
        "$ snyk protect",
        "Successfully applied Snyk patches",
        "",
        "Done in 9.65s.",
        "Done in 217.85s.",
        "yarn install v1.22.10",
        "[1/4] Resolving packages...",
        "success Already up-to-date.",
        "$ yarn run snyk-protect",
        "yarn run v1.22.10",
        "$ snyk protect",
        "Successfully applied Snyk patches",
        "",
        "Done in 3.56s.",
        "Done in 4.49s.",
        "\u001b[93mWARN: bench is installed in editable mode!",
        "",
        "This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`",
        "\u001b[0m",
        "/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')",
        "",
        "\u001b[93mWARN: bench is installed in editable mode!",
        "",
        "This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`",
        "\u001b[0m",
        "get_frappe_commands returned []",
        "\u001b[90m$ /usr/local/bin/virtualenv -q env -p python3\u001b[0m",
        "",
        "\u001b[93mGetting frappe\u001b[0m",
        "\u001b[90m$ git clone https://github.com/frappe/frappe --branch version-13-beta --depth 1 --origin upstream\u001b[0m",
        "",
        "\u001b[93mInstalling frappe\u001b[0m",
        "\u001b[90m$ /home/frappe/frappe-bench/env/bin/pip install -q -U -e /home/frappe/frappe-bench/apps/frappe \u001b[0m",
        "\u001b[90m$ yarn install\u001b[0m",
        "Updating node packages...",
        "",
        "\u001b[93mInstalling node dependencies for frappe\u001b[0m",
        "\u001b[90m$ yarn install\u001b[0m",
        "\u001b[90m$ bench build\u001b[0m",
        "\u001b[92mSUCCESS: Bench /home/frappe/frappe-bench initialized\u001b[0m"
    ]
}

We can test that:

sudo -H -u frappe bash
cd /home/frappe
rm -rf frappe-bench
# bench executable at /usr/local/bin/bench, files at /home/frappe/.bench
bench init /home/frappe/frappe-bench --frappe-path https://github.com/frappe/frappe --frappe-branch version-13-beta --python python3

Output:

frappe@ip-172-30-0-218:~$ bench init /home/frappe/frappe-bench --frappe-path https://github.com/frappe/frappe --frappe-branch version-13-beta --python python3
WARN: bench is installed in editable mode!

This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`

get_frappe_commands returned []
$ /usr/local/bin/virtualenv -q env -p python3

Getting frappe
$ git clone https://github.com/frappe/frappe --branch version-13-beta --depth 1 --origin upstream
Cloning into 'frappe'...
remote: Enumerating objects: 2924, done.
remote: Counting objects: 100% (2924/2924), done.
remote: Compressing objects: 100% (2724/2724), done.
remote: Total 2924 (delta 385), reused 1083 (delta 131), pack-reused 0
Receiving objects: 100% (2924/2924), 11.96 MiB | 2.01 MiB/s, done.
Resolving deltas: 100% (385/385), done.

Installing frappe
$ /home/frappe/frappe-bench/env/bin/pip install -q -U -e /home/frappe/frappe-bench/apps/frappe 
    ERROR: Command errored out with exit status 1:
     command: /home/frappe/frappe-bench/env/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-ev_pbji1/psycopg2-binary/setup.py'"'"'; __file__='"'"'/tmp/pip-install-ev_pbji1/psycopg2-binary/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-uutg3ruj
         cwd: /tmp/pip-install-ev_pbji1/psycopg2-binary/
    Complete output (23 lines):
    running egg_info
    creating /tmp/pip-pip-egg-info-uutg3ruj/psycopg2_binary.egg-info
    writing /tmp/pip-pip-egg-info-uutg3ruj/psycopg2_binary.egg-info/PKG-INFO
    writing dependency_links to /tmp/pip-pip-egg-info-uutg3ruj/psycopg2_binary.egg-info/dependency_links.txt
    writing top-level names to /tmp/pip-pip-egg-info-uutg3ruj/psycopg2_binary.egg-info/top_level.txt
    writing manifest file '/tmp/pip-pip-egg-info-uutg3ruj/psycopg2_binary.egg-info/SOURCES.txt'
    
    Error: pg_config executable not found.
    
    pg_config is required to build psycopg2 from source.  Please add the directory
    containing pg_config to the $PATH or specify the full executable path with the
    option:
    
        python setup.py build_ext --pg-config /path/to/pg_config build ...
    
    or with the pg_config option in 'setup.cfg'.
    
    If you prefer to avoid building psycopg2 from source, please install the PyPI
    'psycopg2-binary' package instead.
    
    For further information please check the 'doc/src/install.rst' file (also at
    <http://initd.org/psycopg/docs/install.html>).
    
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
$ yarn install
yarn install v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning " > [email protected]" has unmet peer dependency "[email protected] - 3".
warning " > [email protected]" has unmet peer dependency "popper.js@^1.16.0".
[4/4] Building fresh packages...
$ yarn run snyk-protect
yarn run v1.22.10
$ snyk protect
Successfully applied Snyk patches

Done in 8.75s.
Done in 158.55s.
Updating node packages...

Installing node dependencies for frappe
$ yarn install
yarn install v1.22.10
[1/4] Resolving packages...
success Already up-to-date.
$ yarn run snyk-protect
yarn run v1.22.10
$ snyk protect
Successfully applied Snyk patches

Done in 3.69s.
Done in 4.58s.
$ bench build
WARN: bench is installed in editable mode!

This is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`

/home/frappe/frappe-bench/env/bin/python: Error while finding module specification for 'frappe.utils.bench_helper' (ModuleNotFoundError: No module named 'frappe')

Traceback (most recent call last):
  File "/usr/local/bin/bench", line 33, in <module>
    sys.exit(load_entry_point('frappe-bench', 'console_scripts', 'bench')())
  File "/home/frappe/.bench/bench/cli.py", line 48, in cli
    if sys.argv[1] in (get_frappe_commands() + ["--site", "--verbose", "--force", "--profile"]):
  File "/home/frappe/.bench/bench/cli.py", line 138, in get_frappe_commands
    print('get_frappe_commands from generate_command_cache()', generate_command_cache())
  File "/home/frappe/.bench/bench/utils.py", line 1067, in generate_command_cache
    raise e
  File "/home/frappe/.bench/bench/utils.py", line 1058, in generate_command_cache
    output = get_cmd_output(command, cwd=sites_path)
  File "/home/frappe/.bench/bench/utils.py", line 517, in get_cmd_output
    output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE).strip()
  File "/usr/lib/python3.8/subprocess.py", line 411, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.8/subprocess.py", line 512, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '/home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper get-frappe-commands' returned non-zero exit status 1.
SUCCESS: Bench /home/frappe/frappe-bench initialized

Conclusion: Installing frappe app failed due to missing pg_config executable, but bench init wrongly continues instead of stopping and throwing error (#1082). Apply PR #1083.

Further, the problem is psycopg2-binary has no binaries for Arm, see #1084.

TL:DR:

sudo apt -y install libpq-dev libssl-dev

After that, bench init will work. 96s using m6g.medium Singapore.

Done in 96.11s.
SUCCESS: Bench /home/frappe/frappe-bench initialized

Switch to ERPNext 13

Hendy tried on Arm64 architecture processor / AWS Graviton2. If all works properly it should be as simple as:

# Note: better update 'bench' first
pip3 install --upgrade frappe-bench

# Update frappe, erpnext, and lovia
bench switch-to-branch version-13 frappe erpnext lovia --upgrade
bench update
bench build

But maybe you will need to install frappe manually, due to problem with psutil. How to install frappe manually:

env/bin/pip install -e ./apps/frappe

Then during bench update, you’ll get:

error /home/frappe/frappe-bench/apps/frappe/node_modules/phantomjs-prebuilt: Command failed.
Exit code: 1
Command: node install.js
Arguments:
Directory: /home/frappe/frappe-bench/apps/frappe/node_modules/phantomjs-prebuilt
Output:
PhantomJS not found on PATH
Unexpected platform or architecture: linux/arm64
It seems there is no binary available for your platform/architecture

It will seem stuck for about 5 minutes then resume, Hendy’s not sure if that works properly or we need to build our own phantomjs?

We also get following Vue warnings:

Building erpnext assets...

✔ Built js/erpnext-web.min.js
✔ Built js/bank-reconciliation-tool.min.js
✔ Built js/item-dashboard.min.js
UNRESOLVED_IMPORT : 'vue/dist/vue.js' is imported by ../erpnext/erpnext/public/js/hub/marketplace.js, but could not be resolved – treating it as an external dependency
Cannot find some dependencies. You may have to run "bench setup requirements" to install them.

UNRESOLVED_IMPORT : 'vue/dist/vue.js' is imported by ../erpnext/erpnext/public/js/hub/vue-plugins.js, but could not be resolved – treating it as an external dependency
Cannot find some dependencies. You may have to run "bench setup requirements" to install them.

MISSING_GLOBAL_NAME : No name was provided for external module 'vue/dist/vue.js' in output.globals – guessing 'Vue'
✔ Built css/erpnext.css
✔ Built css/marketplace.css
✔ Built js/point-of-sale.min.js
✔ Built css/erpnext-web.css
✔ Built js/erpnext.min.js
✔ Built js/marketplace.min.js
✨  Done in 8.63s

So far, ERPNext v13 seems to work. However, we don’t know if there are specific features that aren’t working (Vue related?).

Since phantomjs and phantomjs-prebuilt is no longer in development, and they don’t support Arm64 for now; as long as ERPNext still depends on phantomjs, don’t install ERPNext on Arm64! Existing installations should be migrated to x64.

Troubleshooting ERPNext v13.10.0 on Arm64: pypika

Patching sites...                                                               
Traceback (most recent call last):                                              
  File "/usr/lib/python3.8/runpy.py", line 185, in _run_module_as_main          
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)            
  File "/usr/lib/python3.8/runpy.py", line 111, in _get_module_details
    __import__(pkg_name)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 33, in <
module>
    from frappe.query_builder import get_query_builder, patch_query_execute
  File "/home/frappe/frappe-bench/apps/frappe/frappe/query_builder/__init__.py",
 line 1, in <module> 
    from frappe.query_builder.utils import get_query_builder, patch_query_execut
e
  File "/home/frappe/frappe-bench/apps/frappe/frappe/query_builder/utils.py", li
ne 5, in <module>
    from pypika import Query
ModuleNotFoundError: No module named 'pypika'

After installing “frappe” manually (see above). Then retrying. Now it “works” but with these JS errors, with “rtlcss”:

yarn run v1.22.10
$ FRAPPE_ENV=production node rollup/build.js --skip_frappe
Production mode
✔ Built js/moment-bundle.min.js
✔ Built js/libs.min.js
(node:1936713) UnhandledPromiseRejectionWarning: Error: Cannot find module 'rtlcss'
Require stack:
- /home/frappe/frappe-bench/apps/frappe/rollup/config.js
- /home/frappe/frappe-bench/apps/frappe/rollup/build.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at get_rollup_options_for_css (/home/frappe/frappe-bench/apps/frappe/rollup/config.js:121:14)
    at get_rollup_options (/home/frappe/frappe-bench/apps/frappe/rollup/config.js:32:10)
    at /home/frappe/frappe-bench/apps/frappe/rollup/config.js:216:5
    at Array.map (<anonymous>)
    at get_options_for (/home/frappe/frappe-bench/apps/frappe/rollup/config.js:200:4)
    at build_assets (/home/frappe/frappe-bench/apps/frappe/rollup/build.js:86:18)
    at /home/frappe/frappe-bench/apps/frappe/rollup/build.js:61:30
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:1936713) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1936713) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Done in 2.15s.
Compiling Python files...
$ supervisorctl restart frappe-bench-workers: frappe-bench-web:

Recommendation is we should switch back to x64, otherwise no guarantee it won’t break in the future.

How can we help?