Setup web client with Debian 10

Back to topic.

Back to topic

Installing sao 2020-02-06T00:00:00Z

step by step:

Have you installed trytond? which you said version 5.0.4-2.
Is it able to run with GTK client?
Do you know where is your trytond.conf file located?
if 3 above you are knowing and working, then below steps for sao.


nodejs 8 and above


mkdir ~/trytond
cd trytond
git clone --single-branch --branch 5.0
cd sao
npm install -g bower
npm install -g po2json
npm install grunt-po2json
npm install

After above steps done:
Please go to your trytond.conf

root = ~/trytond/sao
hostname = localhost
listen =

root=~/trytond/sao --> assume you run with same user else use the full path

then run your trytond server.

open your browser should be able to go sao by accessing with port :8000

The follow is ok:

if 3 above you are knowing and working, then below steps for sao.


sudo apt install nodejs
nodejs -v

sudo apt install npm
npm -v

Installing git

sudo apt install git


mkdir ~/trytond
cd trytond
git clone --single-branch --branch 5.0
cd sao
npm install -g bower

than i get:

sudo npm install -g bower
npm WARN npm npm does not support Node.js v10.15.2

I will try with solution:

http s://

sudo apt install curl
curl | sudo sh

than it works

sudo npm install -g bower
npm WARN deprecated bower@1.8.8: We don't recommend using Bower for new projects. Please consider Yarn and Webpack or Parcel. You can read how to migrate legacy project here:
/usr/local/bin/bower -> /usr/local/lib/node_modules/bower/bin/bower
+ bower@1.8.8
updated 1 package in 2.806s

next problem

sudo npm install -g po2json
npm WARN deprecated nomnom@1.8.1: Package no longer supported. Contact for more info.
/usr/local/bin/po2json -> /usr/local/lib/node_modules/po2json/bin/po2json
+ po2json@0.4.5
added 11 packages from 15 contributors in 1.938s

Now i have:

node -v
 npm -v

My http s:// is starting.

access url in browser.

I get Hello World in my browser-

It doesn’t solved my Tryton problem.

Can you please help me?

Why are you saying there is a problem? I see no problem in this log.

By the way, you do not need to install each dependencies manually, you just need to run npm install in the sao folder.

Hello ced,
thank you,
, if i read “WARN deprecated” i think, i have a problem.

npm install

What is my next step to get sao support?

Warning is not a problem, it is just a warning. In Javascript world everything is deprecated faster than a wink.

Nothing just connect to it.

PS: Please avoid using temporary URL, it will prevent a reader later to understand the conversation.

Hello, what did you mean? ?

My new trytond.conf: (added line 24., 25.,26.)

sudo cat /etc/tryton/trytond.conf

root = ~/trytond/sao
hostname = localhost
listen =

Is the /etc/tryton/trytond.conf ok?

sudo service tryton-server stop

new start to get the new value

sudo trytond -c /etc/tryton/trytond.conf

Which browser address must i use to get sao support?


sudo service tryton-server status
● tryton-server.service - Tryton Server WSGI App
   Loaded: loaded (/lib/systemd/system/tryton-server.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Fri 2020-02-07 11:56:24 CET; 2s ago
     Docs: man:trytond,file:/usr/share/doc/tryton-server,file:/usr/share/doc/tryton-server-doc,http:doc/
  Process: 1579 ExecStart=/usr/bin/trytond --config /etc/tryton/trytond.conf --logconf /etc/tryton/trytond_log.conf (code=exited, status=1/
 Main PID: 1579 (code=exited, status=1/FAILURE)

Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Main process exited, code=exited, status=1/FAILURE
Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Failed with result 'exit-code'.
Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Service RestartSec=100ms expired, scheduling restart.
Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Scheduled restart job, restart counter is at 5.
Feb 07 11:56:24 debian systemd[1]: Stopped Tryton Server WSGI App.
Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Start request repeated too quickly.
Feb 07 11:56:24 debian systemd[1]: tryton-server.service: Failed with result 'exit-code'.
Feb 07 11:56:24 debian systemd[1]: Failed to start Tryton Server WSGI App.
lines 1-15/15 (END)

Yes it is junk URL as the name says.

I doubt because because you are using environment variable to link to sao folder which is not supported.
And I doubt that you put the directory really in the user home of the user running trytond as you are using Debian packages which probably uses a dedicated user for that.
So please use absolute path and ensure trytond user has access to it.

Running with systemd hide all the error messages. So you must fetch from systemd the error message (I do not know how to do that because I never use systemd).

The address of the server on port 8000 as you configured in the listen.

My /etc/tryton/trytond.conf

# /etc/tryton/trytond.conf - Configuration file for Tryton Server

# (trytond, trytond-admin, trytond-cron)


# This file contains the most common settings for trytond (Defaults

# are commented).

# For more information install the tryton-server-doc package and read

# /usr/share/doc/tryton-server-doc/html/index.html

# and accordingly

# /usr/share/doc/tryton-server-doc/html/topics/configuration.html



# Settings for the web interface


# The IP/host and port number of the interface

# (Internal default: localhost:8000)


# Listen on all interfaces (IPv4)

#listen =

listen =

#listen =


# Listen on all interfaces (IPv4 and IPv6)

# listen = [:::]:8000

root = ~/trytond/sao

hostname = localhost

listen =


# The hostname for this interface

#hostname =


# The root path to retrieve data for GET requests

# (i.e. namely the path to the web client)

# (Internal default: /var/www/localhost/tryton)

root = /usr/share/tryton-sao/www


# The number of proxy servers in front of trytond.

#num_proxies = 0



# Database related settings


# The URI to connect to the SQL database (following RFC-3986)

# uri = database://username:password@host:port/

# (Internal default: sqlite:// (i.e. a local SQLite database))


# PostgreSQL via Unix domain sockets

# (e.g. PostgreSQL database running on the same machine (localhost))

#uri = postgresql://tryton:tryton@/


# PostgreSQL via TCP/IP

# (e.g. connecting to a PostgreSQL database running on a remote machine or

# by means of md5 authentication. Needs PostgreSQL to be configured to accept

# those connections (pg_hba.conf).)

#uri = postgresql://tryton:tryton@localhost:5432/

uri = postgresql://tryton_test:tryton_test@localhost:5432/


# The path to the directory where the Tryton Server stores files.

# The server must have write permissions to this directory.

# (Internal default: /var/lib/trytond)

path = /var/lib/tryton


# Shall available databases be listed in the client?

#list = True


# The number of retries of the Tryton Server when there are errors

# in a request to the database

#retry = 5


# The primary language, that is used to store entries in translatable

# fields in the database.

#language = en



# The maximum size in bytes for unauthenticated requests (zero means no limit).

#max_size = 2MB


# The maximum size in bytes of an authenticated request (zero means no limit).

#max_size_authenticated = 2GB



# SSL settings

# Activation of SSL for all available protocols.

# Uncomment the following settings for key and certificate.

# SSL is activated by defining privatekey.


# The path to the private key

#privatekey = /etc/ssl/private/ssl-cert-snakeoil.key


# The path to the certificate

#certificate = /etc/ssl/certs/ssl-cert-snakeoil.pem



# Session settings


# A comma separated list of login methods to use for user authentication.

# By default, Tryton supports only the password method which compares the

# password entered by the user against a stored hash.

# Other modules may define other methods (please refer to their documentation).

# The methods are tested following the order of the list.

#authentications = password


# The time (in seconds) until a session expires.

#max_age = 2592000   # (30 days)


# The time (in seconds) until an inactive session is considered invalid for

# special internal tasks, thus requiring to re-confirm the session.

#timeout = 300   # (5 minutes)


# The maximal number of authentication attempts before the server answers

# unconditionally 'Too Many Requests'.

# The counting is done on all attempts over one period of timeout.

#max_attempt = 5


# The maximal number of authentication attempts from the same network before

# the server answers unconditionally 'Too Many Requests'.

# The counting is done on all attempts over a period of timeout.

#max_attempt_ip_network = 300


# The network prefix to apply on IPv4 addresses when counting authentication attempts.

#ip_network_4 = 32


# The network prefix to apply on IPv6 addresses when counting authentication attempts.

#ip_network_6 = 56



# The minimal length required for user passwords.

#length = 8


# The path to a file containing one forbidden password per line.

#forbidden =


# The ratio of non repeated characters for user passwords.

#entropy = 0.75


# The time (in seconds) until a reset password expires.

#reset_timeout = 86400   # (24h)


# The path to the INI file to load as CryptContext:

# <>

# If no path is set, Tryton will use the schemes `bcrypt` or `pbkdf2_sha512`.

#passlib = None



# Mail settings


# The URI to connect to the SMTP server.

# Available protocols are:

# - smtp: simple SMTP

# - smtp+tls: SMTP with STARTTLS

# - smtps: SMTP with SSL

#uri = smtp://localhost:25


# The From address used by the Tryton Server to send emails.

#from = tryton@localhost



# Defines how to store the attachments

# A boolean value to store attachment in the FileStore.



# The prefix to use with the FileStore.

#store_prefix = None



# Allow clients to subscribe to bus channels (Boolean).

#allow_subscribe = False


# The time (in seconds) to keep the connection to the client open

# when using long polling for bus messages.

#long_polling_timeout = 300


# The time (in seconds) a message should be kept in the queue

# before being discarded.

#cache_timeout = 300


# The timeout (in seconds) for the select call when listening

# on a channel.

#select_timeout = 5


# Let the worker queue handle bus messages

#queue = False


# Define the class to use when queue is set to True

#class = trytond.bus.LongPollingBus


# Special Settings


# Various cache size settings


# The number of different models kept in the cache per transaction.

#model = 200


# The number of loaded records kept in the cache. It can also be changed

# locally using the _record_cache_size key in Transaction.context.

#record = 2000


# The number of fields to load with eager Field.loading.

#field = 100


# The minimum number of seconds between two cleanings of the cache.

#clean_timeout = 300



# Activate asynchronous processing of the tasks. Otherwise they are performed at the end of the requests.

#worker = False



# This section allows to override the default generated table names. The main purpose

# is to bypass name length limitations of a database backend.

# Examples:

#account.invoice.line = acc_inv_line = acc_inv_tax


# Module settings


# Some modules are reading configuration parameters from this

# configuration file. These settings only apply when those modules

# are installed.



# The private key to communicate with the chorus service.

#privatekey =


# The certficate to communicate with the chorus service.

#certificate =


# Target URL of the Chorus service

#url =



# The LDAP URL to connect to the server following RFC-2255.

#uri = ldap://host:port/dn?attributes?scope?filter?extensions

# A basic default URL could look like

#uri = ldap://localhost:389/


# The LDAP password used to bind if needed.

#bind_pass =


# If the LDAP server is an Active Directory.

#active_directory = False


# The UID attribute for authentication.

#uid = uid


# If the user shall be created in the database in case it does not exist.

#create_user = False



# The fully qualified name of the method to send SMS. It must take three

# arguments: text, to and from.


# - The sms method just sends a code via SMS to the user. This code can directly

#   be used in the login dialog.

# - The password_sms method sends a code only after the user entered a valid

#   password (two-factor authentication).


# Both methods require that the user has a *mobile* phone number defined

# otherwise he can not be authenticated with those methods.


# This method is required to send SMS.

#function =


# The number from which the SMS are sent.

#from =


# The length of the generated code.

#length = 6


# The time to live for the generated codes in seconds.

#ttl = 300


# The name used in the SMS text.

#name = Tryton



# The number of decimals with which the unit prices are stored

# in the database. The default value is 4.

# Warning: This setting can not be lowered once a database is created.

#price_decimal = 4

Duplicate for better reading:

What should i change to get sao support?
Which line?

FYI, if install production, it will need to install po2json in global for convert the .po file.
This is my experience, I do not know whether need to put in the Git installation procedure

Hi Trytfan,

My example that if you running as the user.
But if you using sudo to run, so I suggest you to use full path
example: /home//trytond/sao

Hello, i want to install a production Tryton system.

sudo npm install -g po2json
npm WARN deprecated nomnom@1.8.1: Package no longer supported. Contact for more info.
/usr/local/bin/po2json -> /usr/local/lib/node_modules/po2json/bin/po2json
+ po2json@0.4.5
updated 1 package in 0.942s





Method Not Allowed

The method is not allowed for the requested URL.


I want to use Tryton as a user.

How must i edit my /etc/tryton/trytond.conf?

Please answer with a code and a line number.

Thank you.

It looks so easy, but i have many trouble. :frowning: ---->

please go inside your sao folder and type:
bash$ pwd

then overwrite:
to the the full path

please go inside your sao folder and type:
bash$ pwd

then overwrite:
to the the full path[quote=“trytfan, post:57, topic:2125”]
root = ~/trytond/sao

Hello, what did you mean?
How can i find post:57, topic:2125? At the rigth side i have find post 57 with scrolling.

Can you the full /etc/tryton/trytond.conf?

Only for better reading:

@ced is it so ok? In post 57 we have the full /etc/tryton/trytond.conf without link.

I didn’t have read the whole discussion, but make things extremely simple. I’m assuming you are using version 5.0.x and you installed the .deb package

  1. setup a database user / password, create a new empty database. Username and password are filled in the tryton.conf file.
  2. just create the most simple /etc/tryton/trytond.conf with only the necessary parts
uri = postgresql://<username>:<password>@localhost:5432/

listen =
root = /usr/share/tryton-sao/www
  1. from the commandline initialize the database. You will be asked for a admin username and password.
trytond-admin -d <database name> -c /etc/tryton/trytond.conf --all -v
  1. start de trytond-server with systemctl start trytond
  2. check with the (GTK) tryton-client if you can connect to trytond-server (localhost:8000)

Congratulation! you have Tryton running. Please get this all working properly before installing Sao.

The next step will be installing Sao.

  1. download the precompiled version from (tryton-sao-5.0.X.tar.gz)
  2. unpack it in /usr/share/tryton-sao/www. Sao will be in a sub directory called package
  3. move all the data from the package a level higher, so all the data resides in /usr/share/tryton-sao/www
  4. get the script and save it in /usr/share/tryton-sao/www. Call it what you want.
  5. modify the script a bit:
    • change FETCHCMD='ftp' to FETCHCMD='curl -L'
    • change UNZIP='/usr/local/bin/7z x' to UNZIP='7z x' (be sure you have 7z installed)
    • change xargs -0 sha256 -b to xargs -0 sha256sum -b (end of the file)
  6. run the script from /usr/share/tryton-sao/www so,
    cd /usr/share/tryton-sao/www & sh <your script>. You will end up with a directory called sao-dependencies-5.0. In this directory you have another directory called bower_components
  7. symlink the bower_components ln -s /usr/share/tryton-sao/www/sao-dependencies-5.0/bower_components/ /usr/share/tryton-sao/www/
  8. make sure the read / write rights for the trytond-server user (systemctl) are correct! chown -R tryton:tryton /usr/share/tryton-sao/www/
  9. make sure trytond-server is running, start your webbrowser and open the url (localhost:8000). You will see Sao coming up.
1 Like

instead of running the script to generate sao-dependencies, you could directly download the latest generated archive at , unpack it and move the bower_components directory inside the sao root.

1 Like

edbo, Post 63, Script:

# little tool to grab all js-dependencies and generate a bower_components/
# directory suitable for tryton-sao

set -eu

UNZIP='/usr/local/bin/7z x'


umask 022

if [ $# -ne 0 ]; then
	echo "usage: $0" >&2
	exit 1


if [ -d "${OUTDIR}" ]; then
	echo "error: output directory already exists: ${OUTDIR}" >&2
	exit 1

EXTRACTDIR=$(mktemp -dt sao-dependencies.XXXXXXXX) || {
	echo "error: unable to create temporary directory" >&2
	exit 1

bootstrap() {
	local V="$1"
	local U="${V}/bootstrap-${V}"
	local O="${OUTDIR}/bower_components/bootstrap/dist"

	${FETCHCMD} -o "${EXTRACTDIR}/bootstrap-${V}" -- "${U}"
	( cd "${EXTRACTDIR}" && ${UNZIP} "bootstrap-${V}" )
	rm "${EXTRACTDIR}/bootstrap-${V}"

	mkdir -p -- "${O}"
	cp -R "${EXTRACTDIR}/bootstrap-${V}-dist"/{css,fonts,js} "${O}"
	rm -rf "${EXTRACTDIR}/bootstrap-${V}-dist"

bootstrap_datetimepicker() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/eonasdan-bootstrap-datetimepicker"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p "${O}"
	cp -R "${EXTRACTDIR}/bootstrap-datetimepicker-${V}/build" "${O}"
	rm -rf "${EXTRACTDIR}/bootstrap-datetimepicker-${V}"

bootstrap_rtl_ondemand() {
	local V="$1"
	local U="${V}-ondemand.tar.gz"
	local O="${OUTDIR}/bower_components/bootstrap-rtl-ondemand"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p "${O}"
	cp -R "${EXTRACTDIR}/bootstrap-rtl-${V}-ondemand/dist" "${O}"
	rm -rf "${EXTRACTDIR}/bootstrap-rtl-${V}-ondemand"

c3() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/c3"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p "${O}"
	cp -R "${EXTRACTDIR}/c3-${V}"/c3{.min,}.css \
		"${EXTRACTDIR}/c3-${V}"/c3{.min,}.js \
		"${EXTRACTDIR}/c3-${V}/extensions" \
	rm "${O}/extensions/chart-bubble/c3.css" \
	cp "${EXTRACTDIR}/c3-${V}/bower.json" "${O}"	# for dependencies
	rm -rf "${EXTRACTDIR}/c3-${V}"

d3() {
	local V="$1"
	local U="${V}/"
	local O="${OUTDIR}/bower_components/d3"

	${FETCHCMD} -o "${EXTRACTDIR}/" -- "${U}"
	mkdir "${EXTRACTDIR}/d3"
	( cd "${EXTRACTDIR}/d3" && ${UNZIP} "../" )
	rm "${EXTRACTDIR}/"

	mkdir -p -- "${O}"
	cp "${EXTRACTDIR}/d3/"d3{.min,}.js "${O}"
	rm -rf "${EXTRACTDIR}/d3"

fullcalendar() {
	local V="$1"
	local U="${V}/fullcalendar-${V}.zip"
	local O="${OUTDIR}/bower_components/fullcalendar/dist"

	${FETCHCMD} -o "${EXTRACTDIR}/fullcalendar-${V}.zip" -- "${U}"
	( cd "${EXTRACTDIR}" && ${UNZIP} "fullcalendar-${V}.zip" )
	rm "${EXTRACTDIR}/fullcalendar-${V}.zip"

	mkdir -p -- "${O}"
	cp -R "${EXTRACTDIR}/fullcalendar-${V}"/fullcalendar{,.min}.js \
		"${EXTRACTDIR}/fullcalendar-${V}"/fullcalendar{,.min}.css \
		"${EXTRACTDIR}/fullcalendar-${V}"/fullcalendar.print{,.min}.css \
		"${EXTRACTDIR}/fullcalendar-${V}"/gcal{.min,}.js \
		"${EXTRACTDIR}/fullcalendar-${V}"/locale{-all.js,} \
	rm -rf "${EXTRACTDIR}/fullcalendar-${V}"

gettext_js() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/gettext.js"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p -- "${O}"
	cp -R "${EXTRACTDIR}/gettext.js-${V}/dist" "${O}"
	rm -rf "${EXTRACTDIR}/gettext.js-${V}"

jquery() {
	local V="$1"
	local U=""
	local O="${OUTDIR}/bower_components/jquery/dist"

	mkdir -p "${O}"
	${FETCHCMD} -o "${O}/jquery.js"		"${U}/jquery-${V}.js"
	${FETCHCMD} -o "${O}/jquery.min.js"	"${U}/jquery-${V}.min.js"
	${FETCHCMD} -o "${O}/"	"${U}/jquery-${V}"

moment() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/moment"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p -- "${O}"
	cp -R "${EXTRACTDIR}/moment-${V}/moment.js" \
		"${EXTRACTDIR}/moment-${V}/min" \
	rm "${O}/min/tests.js"
	rm -rf "${EXTRACTDIR}/moment-${V}"

mousetrap() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/mousetrap"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p -- "${O}"
	cp -R "${EXTRACTDIR}/mousetrap-${V}/"mousetrap{.min,}.js \
		"${EXTRACTDIR}/mousetrap-${V}/plugins" \
	rm -rf "${EXTRACTDIR}/mousetrap-${V}"

papaparse() {
	local V="$1"
	local U="${V}.tar.gz"
	local O="${OUTDIR}/bower_components/papaparse"

	${FETCHCMD} -o- -- "${U}" | tar zxf - -C "${EXTRACTDIR}"

	mkdir -p -- "${O}"
	cp "${EXTRACTDIR}/PapaParse-${V}/"papaparse{.min,}.js "${O}"
	rm -rf "${EXTRACTDIR}/PapaParse-${V}"

# download and extract files
bootstrap			'3.3.7'		# ^3.3.7
bootstrap_datetimepicker	'4.17.47'	# ^4.17
bootstrap_rtl_ondemand		'3.3.4'		# ^3.3.4-ondemand
c3				'0.6.11'	# ^0.6
d3				'5.7.0'		# ^5.0.0 (c3 dependency)
fullcalendar			'3.9.0'		# ^3.0
gettext_js			'0.5.5'		# ^0.5
jquery				'3.3.1'		# ^3
moment				'2.23.0'	# ^2.10
mousetrap			'1.6.2'		# ^1.6
papaparse			'4.6.2'		# ^4.1

# cleanup (ensure it is empty)
rmdir "${EXTRACTDIR}"

# generate sha256
( cd "${OUTDIR}" && find "bower_components" -type f -print0 \
	| xargs -0 sha256 -b ) \
	> "${OUTDIR}/SHA256"

Ah, didn’t know that, but that makes things even easier :smile:

Hello edbo,

can you edit your with for the new solution (sao-dependencies-5.0-12.tar.gz) how to? Or create a new how to?

The how to reads very nice.

Thank you


I can modify the post, but more important is if you got up-and-running :smile: I can make howto’s which reads nice (thanks for the kind words) but it’s main purpose is to get you (and others) up-and-running. So please let us know if you got everything running.