Complete Walk-through Installing DAML/VS Code on Debian Buster (10)

This tutorial is based on a clean install of Debian Buster (10) GNU/Linux, and in combination with Node.js, VS Code, and Java will provide a system to allow the development, testing and support of Daml code.

Operating System (OS): Debian Buster (10)
Kernel: Linux version 4.19.0-14-amd64
Desktop Environment: XFCE 4.12
Terminal: xfce4-terminal

A complete Daml/VS Code installation will require these packages:

Curl: A library & command-line tool or transferring data across various networks
Various: autoconf automake autotools-dev bison build-essential dpkg-dev gcc g++ make
Git: A version control system (VCS) for tracking changes in computer files
Node.js: An open source server environment that supports JavaScript and it's variants
Java: A programming language and computing platform now supported by the Oracle Corporation
VS Studio: Is Microsoft's powerful and platform-agnostic, extensible code editor
Daml: The Digital Asset Markup Language
  1. The use of # is similar to a comment in a program, for information only.
  2. The use of $ indicates the terminal prompt from the system user perspective, and is this case, the $user is ‘quid’. If the #ROOT user is to be used, the terminal prompt will be displayed like this:
  3. This tutorial is aimed at the absolute novice, and has simple commands that are very sequential, even repetitive.
  4. If any of the following packages already exist on your system, execute the commands anyway, it will cause no issue, other than warnings.
  5. Every word or abbreviation after the $ is a command to be executed. Type the short commands in directly but use Copy & Paste for others.
  6. This tutorial commences in a Terminal in the /home/your_user directory.


# Verify if Curl is installed
$ which curl
$ curl
bash: curl: command not found
# Update the APT package
$ sudo apt update
# Install Curl
$ sudo apt install curl
# Current Curl VERSION
$ curl --version
curl 7.64.0 (x86_64-pc-linux-gnu) ...

Systems Building Packages

# autoconf automake autotools-dev bison build-essential
# dpkg-dev gcc g++ make libtool gettext flex
# Update the APT package cache
$ sudo apt update
# Install the systems building packages
$ sudo apt install autoconf automake autotools-dev
$ sudo apt install bison build-essential dpkg-dev
$ sudo apt install gcc g++ make libtool gettext flex


# Verify if Git is installed
$ which git
$ dpkg --list | grep ii | git
bash: git: command not found
# Update the APT package cache
$ sudo apt update
# Install Git
$ sudo apt install git
# Verify Git is installed
$ which git
# Current Git VERSION
$ git --version
git version 2.20.2


# Verify if Node.js is installed
$ which node
$ dpkg --list | grep ii | node
bash: node: command not found
bash: $: command not found
# Update the APT package cache
$ sudo apt update
# Install the latest Node.js (Node.js v16.x) as the ROOT user
$ su root
root@host:/home/quid# apt update
root@host:/home/quid# curl -fsSL | bash -
# Exit ROOT user, to normal $user
root@host:/home/quid# exit
# Install Node.js latest
$ sudo apt install nodejs
# Current Node.js VERSION
$ node --version


# Verify if Java is installed
$ which java
# Simple Java version
$ java --version
openjdk 2020-11-04
OpenJDK Runtime Environment (...)
OpenJDK 64-Bit Server VM (...)
# Identify exact Java version
$ ls /usr/lib/jvm
default-java  java-1.11.0-openjdk-amd64  java-11-openjdk-amd64
# Add Java_PATH to your User settings (~/.bashrc)
# Refer to above for exact JAVA_VERSION which in
# this case is 'java-1.11.0-openjdk-amd64'
$ echo "export JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64" >> ~/.bashrc
$ source ~/.bashrc
# Verify the correct JAVA_HOME is set
$ echo $JAVA_HOME

VS Code

# Verify if VS Code (code) is installed
$ which code
$ dpkg --list | grep ii | code
bash: code: command not found
# Go to the VS Code Editor site
$ firefox

# Select Linux section and scroll down to the 
# 'Debian and Ubuntu based distributions section'
# There are two (2) install methods:
# Method 1:
# Download the .deb and install using DPKG
# Download the required .deb file using a web browser
$ firefox
# Method 2:
# Import the repository package GPG signing key,
# and use Debian's APT to install the package, which
# ensures that it will be subject to regular functional & security updates

# In this example, I will use Method 2
# Change to Downloads directory
$ cd ~/Downloads
# Import the Microsoft GPG signing key
$ wget -qO- | gpg --dearmor >
# Backup the 'sources.list' file
$ sudo cp -v /etc/apt/sources.list /etc/apt/sources.list.bak
# Install the Microsoft GPG signing key
$ sudo install -o root -g root -m 644 /etc/apt/trusted.gpg.d/
$ sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/trusted.gpg.d/] stable main" > /etc/apt/sources.list.d/vscode.list'
# Update the APT package cache
$ sudo apt update
# Install apt-transport-https
$ sudo apt install apt-transport-https
# Update the APT package cache
$ sudo apt update
# Install VS Code, using either of the following commands:
$ sudo apt install code  # Option 1
$ sudo apt install code-insiders  # Option 2
# Current VS Code (code) VERSION
$ code --version

# Test it works directly from the command line
$ code
# Test from System Menu
XFCE >> Applications >> Development >> Visual Studio Code


# Install the Daml Software Development Kit (SDK)
# Visit the correct page using your web browser
$ firefox

# There are two (2) install methods:
# Method 1 [Automatic installation & configuration]:
# To install the SDK on Mac or Linux, do this:
$ curl -sSL | sh
# Note: The installer will setup the PATH variable for you. In order
# for it to take effect, you will have to log out and log in again.
# Method 2 [Manual installation & configuration]:
# Download the compressed tarball, verify the associated signature,
# extract and manually execute the install script.

# Navigate to
$ firefox
# Confirm there is a valid security certificate for this domain

# In this instance, I will use Daml ver. 1.15.0, which is located at
# Just after the Release Notes is a section titled 'Assets'
# There are two (2) files relating to Linux that we will need, the first
# is the actual compressed archive and the second is the GPG signing key(?)

# Next, download these two (2) files into '~/Downloads'
# Change to Downloads directory
$ cd ~/Downloads
$ wget
$ wget

To verify the package signature, you will need the GnuPG (gpg) package

# Check if it is installed
$ gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.

If there is no output from this command, then likely GnuPGP is not installed.
If so, install the 'GnuPGP' package.
# Update APT package cache
$ sudo apt update
$ sudo apt install gpg
# Verify successful installation
$ gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.

Now that GnuPG is correctly installed, you can verify the signature,
after importing the Digital Asset Security Public Key into your keychain.

# Import the package key
$ gpg --keyserver --search 4911A8DFE976ACDFA07130DBE8372C0C1C734C51
gpg: data source: [Note #1]
(1)	Digital Asset Holdings, LLC <> [Note #2]
	  2048 bit RSA key E8372C0C1C734C51, created: 2019-05-16, expires: 2021-05-15 [Note #3]
Keys 1-1 of 1 for "4911A8DFE976ACDFA07130DBE8372C0C1C734C51".  Enter number(s), N)ext, or Q)uit > 1
gpg: /home/quid/.gnupg/trustdb.gpg: trustdb created
gpg: key E8372C0C1C734C51: public key "Digital Asset Holdings, LLC
<>" imported
gpg: Total number processed: 1
gpg:               imported: 1

# [Note]: The IP address of this keyserver is concealed as this forum is publically 
# indexible, and in my mind, this would present an unnecessary attack vector.
# If any of the details in [Note #2] or [Note #3] are different, contact Digital Asset
# Holdings, LLC immediately.

# Ensure that you are still in the Downloads directory
$ pwd
$ ls -al
total 431368
drwxr-xr-x  2 quid quid      4096 Mar  8 18:05 .
drwxr-xr-x 19 quid quid      4096 Mar  8 15:48 ..
-rw-r--r--  1 quid quid 441701989 Mar  4 09:14 daml-sdk-1.15.0-linux.tar.gz
-rw-r--r--  1 quid quid       473 Mar  4 09:14 daml-sdk-1.15.0-linux.tar.gz.asc
-rw-r--r--  1 quid quid       641 Mar  8 15:40

# Now that the key has been successfully imported and verified, use GnuPG to verify
# that the package that you downloaded was in fact, signed by the new key.
$ gpg --verify daml-sdk-1.15.0-linux.tar.gz.asc
gpg: assuming signed data in 'daml-sdk-1.15.0-linux.tar.gz'
gpg: Signature made Thu 04 Mar 2021 09:14:21 NZDT
gpg:                using RSA key E8372C0C1C734C51
gpg: Good signature from "Digital Asset Holdings, LLC <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4911 A8DF E976 ACDF A071  30DB E837 2C0C 1C73 4C51

[Note]: This warning indicates that GnuPG has not been instructed to trust this key.
[Note]: Regardless of the warning, the key has been verified as having signed the package.

# Now that I have confidence in the origin and security of the package, it can be installed
# Identify the correct file
$ ls *.tar.gz
$ tar xzf daml-sdk-1.15.0-linux.tar.gz

# Change directory into the new 'sdk-1.15.0' directory
$ cd sdk-1.15.0

# Execute the installation script
Installing SDK release from directory.
Add DAML Assistant executable to your PATH (in .bash_profile)? [Yes] No
Your /home/quid/.bash_profile has been updated. You need to logout and login again for the change to take effect.
Bash completions installed for DAML assistant.
Zsh completions installed for DAML assistant.
To use them, add '~/.daml/zsh' to your $fpath, e.g. by adding the following
to the beginning of '~/.zshrc' before you call 'compinit':
fpath=(~/.daml/zsh $fpath)

# Update your USER_PROFILE by either logging out & back in,
# or source the USER_PROFILE in the current terminal.
$ source ~/.bash_profile
# Verify the Daml installation has been successful
$ daml version
SDK versions:
  1.11.1 (not installed)
  1.15.0  (default SDK version for new projects)

# [Note]: Adding the Daml Assistant executable to ~/.bash_profile did not
# work on this system. Whereas adding it to ~/.bashrc did.


  • Latest version of Node on new install (16.5.0)
  • Latest version of Yarn on new install (1.22.5)
  • Latest version of VS Code on new install (1.58.2)
  • Latest version of Daml on new install (1.15.0)
  • Added 3 additional systems packages for pre-Daml install
  • Modified 3 issues in the TODO list


  1. Convert tutorial into commands, with minor headings :ballot_box_with_check:
  2. Convert tutorial into commands, with no headings :ballot_box_with_check:
  3. Adapt into Bash script for Debian/Variants ← 60%
  4. Convert Bash script into Haskell program for Debian/Variants ← 0%
  5. Update install tutorial for Daml SDK 1.15.0 :ballot_box_with_check:
  6. Get a life :sunglasses: :ballot_box_with_check:

If there is any feedback, please reply to this message thread.


Nice work, thank you!

I think there are a few steps you might be able to skip, in particular

  1. Install the systems building packages shouldn’t be required.

  2. We also don’t depend on git although you probably want that for your own projects.

  3. JAVA_HOME should be setup automatically by apt afaik. Did you verrify that you have to set this manually?

This isn’t going to work, we only provide x86_64 binaries. You can run the standalone JVM artifacts on some other architectures but not the assistant or the compiler.

1 Like

Thanks for the feedback.

Re the ‘systems building packages’, ordinarily they might not be needed but this was a vanilla install and I did get warning under an ‘install --dry-run’ of Node.js for some, so I threw them all in.

Re Git, again Node.js listed it as a dependency, so in it went.

The Java_HOME was definitely not set by the initial install process. Java was installed successfully, but I had to add the JAVA_HOME using the method I mentioned in ~/.bash_profile.

EDIT: Re the DAML $PATH being set for ~/.bash_profile, this absolutely did not work on this Debian install. I tried numerous times, and it failed. When I added that required $PATH into ~/.bashrc, it worked first time. However I’ll review my ~/.bash* settings, perhaps I have made an error.

Re the x86_32 & ARMv5/7, that was an aspirational goal as I did want to install DAML on a few older machines and my five Raspberry Pi, to use as additional clients in a testing scenario.

In all instances of installing Java, Node.js and VS Code, I followed their Linux instructions exactly with no additional packages or functionalities.

1 Like

Minor quib to appease our marketing department: “Daml” is written in title case and is not an acronym.

As @cocreature mentioned, the Daml Connect binaries themselves are only built for x86_64. This means that the daml cli will not work on other systems. However, if all you want is to run clients on other architectures, you may still be able to use our Java bindings as a library in your own client Java code. You may have to run the codegen on an x86_64 machine, though, which may make the whole process a bit cumbersome. Though I suppose you could develop a Java client entirely under x86_64 then copy your jar over to the other machines, and that should work out. I think.

We’ve not tried any of this (and it’s definitely not supported), but if you do try it please let us know how it goes.


Re the Daml, OK. Mentally I am disputing it’s classification as a non-acronym with the Marketing Department, but I’ll battle that out in my head and win :laughing:

All I wanted was to run clients on a range of Arch (Conceptually) but I phrased that poorly. Using Raspberry Pi (RPv3/4) for development & testing as much as I do, they’ve become a defacto Desktop in my mind, as they run a Desktop OS, but the reality is they are but an SBC.

I will start here: Search — Daml SDK 1.10.0 documentation and if I have queries on the process, I’ll ask for some guidance :+1:t2:


Editing to tutorial:

  1. Adjust minor typos
  2. Clarify various terms
  3. Split overly long lines
  4. Adjust installation process
  5. Update Daml ver 1.10.2 > 1.11.1
  6. Convert the term ‘DAML’ to ‘Daml’
  7. Change section headings from H2 > H3
  8. Truncated package number variants to (…)
1 Like

Just revising this now after 2 week of learning & configuring hardware. I have planned for a complete testing scenario to help me further understand how contracts & ledgers interact.

Current Devices
  1. AMD64 Desktop (Ubuntu 20.04) [Active, Daml, Java, Node Build machine]
  2. x86_64 Laptop (Ubuntu 20.04) [Planned, Daml, Java, Node, Bank]
  3. ARM6 Raspberry Pi v3 DietPi [Active, Java, Node, Ledger]
  4. ARM6 Raspberry Pi v3 DietPi [Active, Java, Node, Bike_Shop]
  5. ARM6 Raspberry Pi v3 DietPi [Planned, Java, Node, Food_Shop]
  6. ARM6 Raspberry Pi v3 DietPi [Planned, Java, Node, Rental_Agency]

Referring to what you wrote above, I can likely use machines 1 & 2 as full Daml Development machines, and (3…6) as Client Nodes only. I’d plan to simulate a Bank, an independent Ledger system and some nodes, all of which would ostensibly be their own independent business, much in the same vein as @fabio.tudone excellent post on the Rental Property Smart Contract and @kctam article on the Bike Shop Smart Contract.

I should be able to simulate this:

Happy Town

Bike_Shop <-> Bike_Customer_1
Bike_Shop <-> Bike_Customer_2
Bike_Shop <-> Bike_Customer_3
Bike_Shop <-> Bike_Customer_X
Food_Shop <-> Bike_Customer_1
Food_Shop <-> Bike_Customer_2
Food_Shop <-> Bike_Customer_3
Food_Shop <-> Bike_Customer_X
Rental_Agency <-> Rental_Customer_1
Rental_Agency <-> Rental_Customer_2
Rental_Agency <-> Rental_Customer_3
Rental_Agency <-> Rental_Customer_X
Bike_Shop <-> Retail_Bank
Rental_Agency <-> Retail_Bank
Food_Shop <-> Retail_Bank
Bike_Shop <-> Ledger
Food_Shop <-> Ledger
Rental_Agency <-> Ledger
Retail_Bank <-> Ledger

From what I have read so far, Codegen can be used on the Desktop machine to make “to generate Java, Scala, and JavaScript/TypeScript classes representing Daml contract templates”, Daml codegen — Daml SDK 1.11.1 documentation

Once these new assets are built, how are they actioned on non-Daml machines? Can they run as headless programs? Do they need a UI? This further use is beyond the edge of my current knowledge, so any guidance or reference much appreciated.

1 Like

Codegen makes helpful components for the frontend/UI of your application to interact easily with the underlying Daml (such as sending commands to the ledger, reading contracts off of it, etc.). So no code created with the codegen tool doesn’t depend on Daml being on the machine the frontend applications are running on. And yes your programs still need the rest of the UI made for them, this tool just makes doing that work a bit easier.

So you are saying that there is currently no method that Daml provides that will allow you to be aware of a contract completion, error or requirement for variance, that does not rely on UI assets?

After writing that, I thought back to the Bike Shop example, and realised that at each of various stages, each of the parties would need to provide assent and input, so that would need a UI.

However surely there are use cases in which a smart contract could initiate, update, complete and archive without active participation? The selling of a commodity based on Volume X becoming priced at value Y etc? The triggering of a commodity purchase based on a specific event, like availability?

Or am I missing the point of smart contracts?

I think in this case what you’re looking for is Daml Triggers which is how you’d have automation respond to things happening on the ledger.

1 Like

Thank you, I think this is exactly what I was after.

… perhaps if I was not so weary I might have thought to search the Daml docs/ for errrr … the term ‘trigger’ :man_facepalming:t2:

1 Like

I think of a Daml ledger as a passive arbiter between parties. Each contract states a bunch of actions that parties can take, and the agreed-upon consequences of these actions.

But parties still need to actually take action for anything to happen.

That does not necessarily imply the presence of a human and a visual UI, though. You can definitely program a headless Java (or JavaScript) application and give it your credentials so it can act as you on the ledger.

An issue you will have to solve if you want to write an external application that interacts with the ledger is that the ledger API is defined in terms of Daml types. When you define a template, and its choices, you (somewhat implicitly) define a Daml data type to serve as the choice arguments. For example, in the default daml new project, the template Asset defines a choice as:

    controller owner can
      Give : AssetId
          newOwner : Party
          create this with
            owner = newOwner

which implicitly defines a data type equivalent to the Daml declaration

data Give = Give with newOwner: Party

and configures the ledger API to expect that data type when external parties want to exercise that choice. At the network level, we use either protobuf or JSON (depending on whether you use the “raw”, gRPC “Ledger API”, or the “HTTP JSON” API), which means that in order to interact with contracts of this template from your own code, you need to:

  1. Figure out how to establish a connection to the API (HTTP/gRPC).
  2. Upon receiving data, figure out how to map raw JSON/protobuf blobs to objects in your programming language.
  3. In order to send data (i.e. exercise choices), figure out how to turn application-level data objects in your app into protobuf/JSON blobs that the Daml system will ultimately accept.

Our language bindings help with 1, while our codegens help with 2 and 3. It is perfectly possible to do without either (which would be your only option if you want to use a language that is neither Java nor JS), but using them will definitely give you a head start.

Either way, this is just about the way in which your client applications communicate with the ledger. What happens on your end of the link is entirely up to you (well, your code): whether that’s a UI (web, desktop, cli, …) with a human in front of it, or a simple procedural system (buy if price under target, sell if price above, etc.), or a complex AI.

1 Like

Thank you for that excellent reply. I understand the underlying model a bit more now. Reviewing my original query, I see that I was asking ‘can Daml do things of value without a UI?’, the answer being yes it can.

… that is interesting, it had not occurred to me
that this was possible :+1:t2:

1 Like