Skip to content


We provide a Node 10.14 image (and other versions) that run inside of an enclave:

docker pull


Let's look at a little hello world program. First, we need to start a node container. We determine which SGX device to mount with function determine_sgx_device.

docker run -it $MOUNT_SGXDEVICE -p3000:3000 sh

In case you have no sgx driver installed, the programs will then run in SIM mode, i.e., the SCONE software runs but in native mode and not inside an enclave.

Do not add npm

The new node container images have npm already installed. If one would add nodejs-npm with apk, the native version will be installed and the SCONE version is replaced.

# DO NOT EXECUTE apk add --no-cache nodejs-npm #

Ensure we can run even in a resource-constrainted VM by setting the maximum heap size to a reasonable value of 1GB:

export SCONE_HEAP=1G

We create a new application myapp:

mkdir myapp
cd myapp
cat > package.json << EOF
  "name": "myapp",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "author": "",
  "license": "ISC"

We install express with the help of npm:

npm install express --save

Let's store the hello world code:

cat > app.js << EOF
var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello World!');
app.listen(3000, function () {
  console.log('Example app listening on port 3000!');

We can run this application inside of an enclave with node. We can also enable some debug messages by setting environment variable SCONE_VERSION=1 to print that we run inside of an enclave:

SCONE_VERSION=1 node app.js

This results in an output like this:

export SCONE_SLOTS=256
export SCONE_MMAP32BIT=0
export SCONE_SSPINS=100
export SCONE_SSLEEP=4000
export SCONE_HEAP=4294967296
export SCONE_STACK=4194304
export SCONE_CONFIG=/etc/sgx-musl.conf
export SCONE_MODE=hw
export SCONE_VARYS=no
export SCONE_ALLOW_DLOPEN=yes (unprotected)
Revision: e349ed6e4821f0cbfe895413c616409848216173 (Wed Feb 28 19:28:04 2018 +0100)
Branch: master
Configure options: --enable-shared --enable-debug --prefix=/builds/scone/subtree-scone/built/cross-compiler/x86_64-linux-musl

Enclave hash: 28cf4f0953ba54af02b9d042fa2ec88a832d749ae4e5395cabd50369e72a5dcb
Example app listening on port 3000!

You can now try to send a request to myapp from another shell in the container. Assuming that you did not start a new container in meantime, execute in another shell of your host:

docker exec -it $(docker ps -l -q) sh

Inside of the container, first install curl and then query myapp:

apk add --no-cache curl
curl localhost:3000/

This results in an output like this:

Hello World!/ #

Potential error messages:

Could not create enclave: Error opening SGX device

Your machine / container does not support SGX. Set mode to automatic via SCONE_MODE=AUTO: in AUTO mode, SCONE will use SGX enclaves when available and emulation mode otherwise.


Your machine / container has most likely too little memory: the Linux OOM (Out Of Memory) killer, terminated your program. Try to reduce memory size by reducing environment variable SCONE_HEAP appropriately.

errno ENOSYS

SCONE switches off fork by default. If you spawn processes, there will be some error message like: npm ERR! spawn ENOSYS

Environment variables

SGXv1 cannot dynamically increase the memory of an enclave. Hence, we have to determine the maximum heap (and stack) size at program start: you can increase the heap by setting environment variable SCONE_HEAP, e.g., SCONE_HEAP=8G. In case you run out of memory inside the enclave, increase the heap size. In case your program gets killed by the OS, you might have selected a too large heap that is not supported by your VM or your host.

Similarily, you can increase the stack size of threads running inside of enclaves by setting environment variable SCONE_STACK.

Environment variable SCONE_VERSION=1 prints debug messages - to show that the program runs inside of an enclave.

SCONE_MODE=hw enforce that program runs in hardware enclave. By default, we set SCONE_MODE=auto which uses hardware enclave if available and software emulation otherwise.


The above example, you could more easily put the following text in a Dockerfile:

RUN apk add --no-cache nodejs-npm \
  && mkdir myapp \
  && cd myapp \
  && echo "{" > package.json \
  && echo '"name": "myapp",' >> package.json \
  && echo '"version": "1.0.0",' >> package.json \
  && echo '"description": "",' >> package.json \
  && echo '"main": "app.js",' >> package.json \
  && echo '"scripts":' >> package.json { \
  && echo '  "test": "echo \"Error: no test specified\" && exit 1"' >> package.json \
  && echo '},' >> package.json \
  && echo '"author": "",' >> package.json \
  && echo '"license": "ISC"' >> package.json \
  && echo '}' >> package.json \
  && npm install express --save \
  && echo "var express = require('express');" > app.js \
  && echo "var app = express();" >> app.js \
  && echo "app.get('/', function (req, res) {" >> app.js \
  && echo "  res.send('Hello World!');" >> app.js \
  && echo "});" >> app.js \
  && echo "app.listen(3000, function () {" >> app.js \
  && echo "  console.log('Example app listening on port 3000!');" >> app.js \
  && echo "});" >> app.js 

CMD SCONE_VERSION=1 node /myapp/app.js

Now create an image myapp as follows:

docker build -t myapp .

You can run a container of this image as a daemon as follows:

docker run -d -p 3000:3000 myapp

You can now query myapp as follows:

curl localhost:3000

This results in an output like this:

Hello World!

Attestation and Secret Provisioning

We describe how to attest a node application and to provision secrets to the node app here.