Use ssh to host a remote git repo

First, NEVER use a file synchronization service such as Nextcloud or Dropbox to synchronize git repos among multiple users. These and similar services should NEVER be used to synchronize git repo’s because they don’t synchronize everyone simultaneously.

For example, if I push to a local repo in my ~/Nextcloud directory, another developer could be pushing to their local repo at about the same time, and there will be a race between our Nextcloud clients to see whose updates make it to the Nextcloud server first. The best outcome is that Nextcloud will notify the loser of a sync collision (a file was modified locally at the same time it was modified on the server), and that the collision will need to be corrected manually. The worst outcome is that the loser will lose their commit entirely (their local repo will be overwritten by the copy on the server from the winning user), or the server repo will be corrupted with some files from the first user and some from the second user. Uggg! This is NOT what you want to have happen.

Only a git push command should be used to update an upstream server. The upstream repo will be locked and the push will be done in an atomic action. This is the only way to preserve repo integrity!

Here is my setup, note that it requires having ssh login capability to the server. I use FreeBSD for my server OS, but this procedure applies equally to Linux.

Step 1. Create a login user, the git repo will be stored in their user directory. You can put more than one git repo in the user directory, but all the repos will have common access (i.e. control is to the user directory, not to the repos in the directory).

Step 2. Create a public/private ssh key to access the git repo with (more correctly, to access the user account that has the git repos), and add the public key to the /home/username/.ssh/authorized_keys file.

You can use a single ssh key and give the private key to each real user who needs access, or better, each real user has their own ssh key and you add all their public keys to the authorized_keys file (this way you can easily remove access from a single user by removing their public key from the authorized_keys file).

Step 3. Create a bare repo in the user directory. E.g. sudo -u username git init –bare repo_name.git

Now you have two choices, depending on whether you have started writing code yet.

Step 4a. If you have not started development yet, commit a file from the server so the repo has at least one commit. Then from your dev workstation, clone the repo using the ssh protocol. After that you write code, commit locally, and push your commits to the upstream origin repo as you would with any other cloned project.

Step 4b. If you have started writing code already (i.e. if you already have a repo with commits), add an origin or upstream ssh protocol remote to your local repo and push it to the empty repo on the server.

This approach maintains complete control over the repo and is easy to setup. It has worked well for me with small projects and a few developers. Compared to GitHub, the primary technical difference is the loss of pull requests (which is a GitHub workflow, not a feature of Git), but in a small team everyone is likely committing directly anyway.

Happy coding.


MyWind MariaDb / MySQL Database

I was both surprised and pleased to see a flury of recent interest in my MyWind database on GitHub, there have been 18 forks in the last month!

MyWind is a re-engineering of the Northwind database provided with Microsoft Access for use with MariaDb and MySQL. Northwind was a sample database and tutorial schema for managing small business customers, orders, inventory, purchasing, suppliers, shipping, and employees.

I provided MyWind using the BSD license, meaning you are free to use MyWind as you please, including commercially, so long as you keep my copyright notice and accept my disclaimer of liability. Enjoy!

Configure Tryton to use PostgreSQL

In this post I will install and configure PostgreSQL as the Tryton data tier. If you have not installed Tryton yet you should start with my post Install Tryton on FreeBSD 13.

In Install Tryton on FreeBSD 13, I used SQLite for for basic testing. However, real-world enterprise use with multiple users interacting simultaneously requires high concurrency and ACID compliance for effective and reliable operation. For production, Tryton uses PostgreSQL for its backend or data tier.

Install PostgreSQL

Install the latest version of PostgreSQL (currently 14.1).

% sudo pkg install postgresql14-server

The installation procedure creates a “postgres” user who owns the PostgreSQL files and the postgres server process. The installed configuration file (/var/db/postgres/data14/postgresql.conf) allows access only from the localhost, which will be sufficient since trytond is running locally.

Confirm PostgreSQL installed correctly.

% pg_config --version

Edit /etc/rc.conf to start the server at startup.

% sudo vi /etc/rc.conf

Initialize a database cluster (one or more databases managed by a single postgresql instance) and start postgresql.

% sudo /usr/local/etc/rc.d/postgresql initdb
% sudo service postgresql start
% sudo service postgresql status

Use the PostgreSQL createuser command to create a tryton” super-user.

% sudo su postgres
$ createuser -sdrP tryton
Enter password for new role:
Enter it again:
$ exit

and restart PostgreSQL.

% sudo service postgresql restart

Confirm localhost can connect to the PostgreSQL server (the “-W” switch causes psql to prompt for the user password).

% psql --username=tryton -W --list
List of databases
   Name    | Owner    | Encoding | Collate | Ctype   | Access privileges
 postgres  | postgres | UTF8     | C       | C.UTF-8 |
 template0 | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(3 rows)

Install psycopg2

trytond uses psycopg2 to connect to postgresql. Install psycopg2 into the virtual environment created for trytond.

(env) [~/work/trytond]$ pip install psycopg2

Edit trytond.conf to use PostgreSQL

Edit ~/work/trytond/trytond.conf to specify using PostgreSQL backend.

# connect to postgresql using a TCIP/IP port
#uri = postgresql://tryton:password@localhost:5432
# connect to postgresql using a Unix socket
uri = postgresql://tryton:password@/

root = /home/dale/work/sao

Create a Tryton database

I need to use the PostgreSQL createdb command to create a database for Tryton,

% sudo su postgres
$ createdb scc

I will use the psql utility to verify the database was created, and then return to my own user name.

$ psql
psql (14.1)
Type "help" for help.

postgres=# \l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
 postgres  | postgres | UTF8     | C       | C.UTF-8 |
 scc       | postgres | UTF8     | C       | C.UTF-8 |
 template0 | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(4 rows)

postgres=# \q
$ ^D

Finally I will initialize the database using the Tryton trytond-admin utility.

I will need to activate the virtualenv created for trytond in order to use trytond-admin.

% bash
[~/work/trytond]$ source env/bin/activate
(env) [dale@starlord ~/work/trytond]$ trytond-admin -c ./trytond.conf -d scc --all -v
"admin" email for "scc":
"admin" password for "scc":
"admin" password confirmation:
(env) [~/work/trytond]$

Start trytond

Start trytond specifying the updated configuration file. Notice I will not specify a database as I did when using SQLite. The database will be selected by the Tryton client.

(env) [~/work/trytond]$ env/bin/trytond -c ./trytond.conf

Access Tryton

You can now use the Tryton client to connect to the Tryton server (trytond). A wizard will lead you through the interactive configuration, which will be covered in a seperate post.

Install Tryton sao web client on FreeBSD v13

In this post I will install sao, the Tryton web client, to use with an existing Tryton installation. If you have not installed Tryton yet you will need to start with my post Install Tryton on FreeBSD 13.


Tryton is open source business software of the type popularly known as ERP (Enterprise Resource Plannning). As described in Install Tryton on FreeBSD 13, Tryton follows a three-tier architecture model with the presentation tier consisting of one, or both, of the following:

  • tryton, the Tryton desktop client.
  • sao, the Tryton web client.

The Tryton desktop client was included when Tryton was first released in 2008, sao was released more recently in 2015. Lay users will likely perceive sao simply as a Tryton web app, but distingishing between the tiers will still be important for system integrators and developers as shown in the following diagram (which arguably has its’ own simplifications).

Tryton System Architecture

The data tier is PostgreSQL, the logic tier is trytond, and the presentation tier is the Tryton client and/or sao (the web browser is only the display for sao).

Install Node

sao is a JavaScript application that runs server-side on the Node.js runtime environment. npm, the Node Package Manager will also be required, and installing npm will install node as a dependency.

% sudo pkg install npm-node17

Install Git

git will be required by npm to install sao.  Install git now if it is not already installed.

% sudo pkg install git

Install sao

Download the sao package from the Tryton project archive to a working directory. The version of sao downloaded must be the same as the version of trytond that is installed.

% cd ~/work
% wget

For convenience, the last version of sao is also provided for convenience, the last version is updated when there is a new release.

% wget

Extract sao from the downloaded archive package, rename the extracted directory, and create a symlink for convenience in configuring trytond and for updating sao.

% cd ~/work
% tar -xf ~/work/tryton-sao-6.2.3.tgz
% tar -xf ~/work/tryton-sao-last.tgz
% mv package sao-6.2.3
% ln -s sao-6.2.3 sao

Install sao following the instructions in the extracted file.

% cd sao
% npm install --production --legacy-peer-deps

You may notice some ominous warnings regarding grunt-xgettext and grunt-po2json during installation, but they can safely be ignored. These packages are required only for development, they are not involved in the running of sao (like all the devDependencies).

npm WARN grunt-xgettext@0.3.5 requires a peer of grunt@~0.4.5 but none is installed. You must install peer dependencies yourself.
npm WARN grunt-po2json@0.3.0 requires a peer of grunt@~0.4.1 but none is installed. You must install peer dependencies yourself.

Configure trytond

trytond reads a trytond.conf configuration file to set operating conditions. Edit ~/work/trytond/trytond.conf to specify the location of sao.

root = /home/dale/work/sao

Start trytond

Starting trytond within a tmux session will prevent trytond from being terminated if the ssh connection to the server is broken. In other words, you can safely break your ssh connection to the server and trytond will stay running. Also the notices that are output by trytond to the shell can be reviewed after re-connecting.

(env) dale@starlord:~/work/trytond$ tmux
(env) dale@starlord:~/work/trytond$ env/bin/trytond -v -c ./trytond.conf -d test_db
25690 34374492160 [2022-01-19 20:16:19,365] WARNING werkzeug  * Running on all addresses.
   WARNING: This is a development server. Do not use it in a production deployment.
25690 34374492160 [2022-01-19 20:16:19,366] INFO werkzeug  * Running on (Press CTRL+C to quit)

Connect to Tryton web app

Start a web browser and connect to the Tryton server URL with the assigned port.

trytond listens on port 8000, ensure the port is open and or forwarded if you are using a virtual machine.

Login with a valid user name and password, such as the admin user and password entered when the database was initialized. The rendered sao interface is essentially identical to the Tryton desktop client (as much as is possible).