Vo
Databases AWS

Virtuoso Open Source Edition 7.2.17 on AWS User Guide

| Product: Virtuoso Open Source Edition 7.2.17 on Ubuntu 24.04

Overview

This guide covers launching and using the Virtuoso Open Source Edition 7.2.17 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened Neo4j & Graph and RDF Databases AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. Every product in the listing is described at /guides/graph-databases-aws/.

Virtuoso is a multi model data server from OpenLink Software: one self contained daemon (virtuoso-t) that is at once an RDF triplestore with a SPARQL endpoint, a relational SQL engine and a built in HTTP server, administered through the Conductor web console. It is the engine behind DBpedia. Virtuoso Open Source Edition is licensed under the GNU General Public License, version 2.

What cloudimg adds to the upstream build:

  • No default login. Virtuoso ships dba/dba and a dav account. On first boot the image creates a fresh database for the instance, sets dba and dav to unique 24 character passwords, and re-keys every other built in account to a random value nobody records. Nothing listens until that has finished; if any step fails, Virtuoso and nginx stay stopped.
  • HTTPS from the first boot. nginx serves the Conductor, the SPARQL endpoint and WebDAV on port 443 with a certificate generated on the instance for its own hostname. Port 80 only redirects to HTTPS, and requests for any other hostname are dropped.
  • Database ports kept private. The SQL / ODBC server (127.0.0.1:1111) and Virtuoso's HTTP server (127.0.0.1:8890) listen on loopback only. Only SSH, 80 and 443 are reachable.
  • Instance metadata blocked for the database. Virtuoso can fetch remote URLs (SPARQL LOAD, the Sponger, http_get()). The virtuoso and nginx services cannot reach the EC2 instance metadata service, and the AMI requires IMDSv2.
  • Fully patched at build time, with Ubuntu's unattended security updates left on.

What is on the image: Ubuntu 24.04 LTS, Virtuoso Open Source Edition 7.2.17 (the official OpenLink build 07.20.3243, with the Conductor installed) in /opt/virtuoso, nginx, and the cloudimg first boot service.

Connecting to your instance

Version SSH user Web console
Virtuoso Open Source Edition 7.2.17 on Ubuntu 24.04 ubuntu https://<public-dns>/conductor/

Prerequisites

  1. An AWS account and permission to launch EC2 instances
  2. An EC2 key pair in the Region you launch in
  3. A security group that allows TCP 22 from your own address, and TCP 443 (and optionally 80, which only redirects) from the clients that will use the Conductor, SPARQL or WebDAV. Never open 1111 or 8890: they listen on loopback only.

Recommended instance type: m5.large (2 vCPU, 8 GiB). The memory settings in /etc/virtuoso/virtuoso.ini (NumberOfBuffers, MaxDirtyBuffers) are sized for it; raise them with the instance size for large datasets.

Step 1: Launch the instance

Option A: AWS Marketplace console

  1. Open the cloudimg Hardened Neo4j & Graph and RDF Databases AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
  2. Choose Launch your software, then in Version choose Virtuoso Open Source Edition 7.2.17 on Ubuntu 24.04 - YYYY-MM-DD and your Region.
  3. Instance type: m5.large is recommended.
  4. Key pair: choose your EC2 key pair.
  5. Security group: TCP 22 from your own address; TCP 443 (and 80) from your clients.
  6. Launch. First boot takes about a minute after the instance is reachable.

Option B: AWS CLI

Run this on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the key pair, security group and subnet with your own:

aws ec2 run-instances \
  --image-id ami-0123456789abcdef0 \
  --instance-type m5.large \
  --key-name my-key-pair \
  --security-group-ids sg-0123456789abcdef0 \
  --subnet-id subnet-0123456789abcdef0 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=virtuoso}]'

The AMI already requires IMDSv2, so you do not need --metadata-options.

Step 2: Connect via SSH

ssh -i my-key-pair.pem ubuntu@<public-ip>

The login banner shows the Conductor and SPARQL URLs for this instance.

Step 3: Check the services

systemctl is-active virtuoso nginx virtuoso-opensource-firstboot
active
active
active

virtuoso-opensource-firstboot is a one time unit: it reports active once first boot has finished. virtuoso runs the virtuoso-t daemon as the unprivileged virtuoso user, and nginx fronts it on 80 and 443.

Step 4: Check what listens on the network

sudo ss -tlnp | grep -E ':(22|80|443|1111|8890) '
0.0.0.0:80     nginx
0.0.0.0:22     sshd
0.0.0.0:443    nginx
127.0.0.1:1111 virtuoso-t
127.0.0.1:8890 virtuoso-t
[::]:80        nginx
[::]:22        sshd
[::]:443       nginx

Only SSH and nginx listen on the network. The Virtuoso SQL server (1111) and HTTP server (8890) accept local connections only.

Step 5: Find your credentials

First boot writes this instance's passwords to a root only file (mode 0600). List the settings it holds:

sudo grep -oE '^[A-Z_]+=' /root/virtuoso-opensource-credentials.txt
VIRTUOSO_HOST=
VIRTUOSO_CONDUCTOR_URL=
VIRTUOSO_SPARQL_URL=
VIRTUOSO_ADMIN_USER=
VIRTUOSO_DBA_PASSWORD=
VIRTUOSO_DAV_USER=
VIRTUOSO_DAV_PASSWORD=

Show the whole file with sudo cat /root/virtuoso-opensource-credentials.txt. It looks like this, with your instance's own values:

VIRTUOSO_HOST=ec2-203-0-113-10.compute-1.amazonaws.com
VIRTUOSO_CONDUCTOR_URL=https://ec2-203-0-113-10.compute-1.amazonaws.com/conductor/
VIRTUOSO_SPARQL_URL=https://ec2-203-0-113-10.compute-1.amazonaws.com/sparql
VIRTUOSO_ADMIN_USER=dba
VIRTUOSO_DBA_PASSWORD=<VIRTUOSO_DBA_PASSWORD>
VIRTUOSO_DAV_USER=dav
VIRTUOSO_DAV_PASSWORD=<VIRTUOSO_DAV_PASSWORD>

The hostname is the instance's public DNS name from the EC2 instance metadata service. It is never taken from a web request.

Step 6: Check HTTPS and the certificate

Port 80 redirects to HTTPS, and the HTTPS front answers with the certificate made on this instance:

H=$(sudo grep '^VIRTUOSO_HOST=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/conductor/"
curl -s --cacert /etc/ssl/virtuoso/virtuoso.crt --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}\n' "https://$H/conductor/"
openssl x509 -in /etc/ssl/virtuoso/virtuoso.crt -noout -subject -ext subjectAltName
301 https://ec2-203-0-113-10.compute-1.amazonaws.com/conductor/
200
subject=CN = ec2-203-0-113-10.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
    DNS:ec2-203-0-113-10.compute-1.amazonaws.com, IP Address:203.0.113.10, IP Address:172.31.82.241, DNS:ip-172-31-82-241.ec2.internal, IP Address:127.0.0.1, DNS:localhost

The certificate is self signed, so your browser warns the first time. Check that the fingerprint matches before accepting it (openssl x509 -in /etc/ssl/virtuoso/virtuoso.crt -noout -fingerprint -sha256 on the instance), or install a certificate from your own CA (Step 13).

Step 7: Query the SQL engine

The isql client connects to the loopback SQL server. Use the dba password from the credentials file. The sample DBA.DEMO_CUSTOMERS table returns three rows:

export LD_LIBRARY_PATH=/opt/virtuoso/lib
DBA=$(sudo grep '^VIRTUOSO_DBA_PASSWORD=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
/opt/virtuoso/bin/isql 127.0.0.1:1111 dba "$DBA" exec="SELECT ID, NAME, CITY FROM DBA.DEMO_CUSTOMERS ORDER BY ID;"
ID                NAME                 CITY
INTEGER NOT NULL  VARCHAR NOT NULL     VARCHAR
_______________________________________________________________________________

1                 Ada Lovelace         London
2                 Alan Turing          Manchester
3                 Grace Hopper         New York

3 Rows. -- 1 msec.

The upstream default dba/dba login is refused by Virtuoso itself:

OUT=$(/opt/virtuoso/bin/isql 127.0.0.1:1111 dba dba exec="SELECT 1;" 2>&1 || true)
grep -o 'Error 28000.*' <<<"$OUT"
Error 28000: [Virtuoso Driver]CL034: Bad login

Virtuoso blocks a client address for 60 seconds after four failed logins (SQL and HTTP together), so a mistyped password a few times in a row locks you out for a minute.

Step 8: Sign in to the Conductor

Open https://<public-dns>/conductor/ in your browser, accept the self signed certificate, and sign in with the account dba and VIRTUOSO_DBA_PASSWORD:

The Virtuoso Conductor login page served over HTTPS by the cloudimg image, with the Account and Password fields and the navigation bar for Home, System Admin, Database, Replication, Web Application Server, XML, Web Services, Linked Data and NNTP

The Database tab lists the SQL catalogs and lets you create tables, views and procedures:

The Virtuoso Conductor Database tab, logged in as dba, showing the Schema Objects browser with the ACME, DB, GRAPHQL, PKI, PUMP, UDDI, VAD, WEBDAV, WS and _2PC catalogs and the Create Table, Create View, Create Procedure and Export Schema actions

Database > Interactive SQL runs SQL in the browser. Here the sample table returns its three rows:

The Virtuoso Conductor Interactive SQL page showing the query result for SELECT ID, NAME, EMAIL, CITY FROM DBA.DEMO_CUSTOMERS with three rows for Ada Lovelace in London, Alan Turing in Manchester and Grace Hopper in New York

Linked Data > SPARQL runs SPARQL with the dba account. With the Default Graph IRI set to http://cloudimg.example/catalog, the sample graph returns its triples:

The Virtuoso Conductor SPARQL Execution page with the Default Graph IRI set to http://cloudimg.example/catalog and the query SELECT ?s ?p ?o WHERE { ?s ?p ?o } returning three triples: product 1 labelled Virtuoso Open Source Edition and described as a Multi-model RDF and SQL database, and product 2 labelled cloudimg AWS Marketplace image

System Admin shows the server dashboard and holds User Accounts, Parameters, Packages, Backup and the Scheduler:

The Virtuoso Conductor System Admin dashboard showing version 07.20.3243, the HTTP server counters, the database disk statistics, the master and temp database space allocation and the transaction log /var/lib/virtuoso/db/virtuoso.trx

Step 9: Use the SPARQL endpoint

https://<public-dns>/sparql is the standard SPARQL protocol endpoint, with a query form for browsers:

The Virtuoso SPARQL Query Editor at /sparql with the Default Data Set Name field, the query text SELECT * WHERE { ?s ?p ?o } LIMIT 20, the Results Format selector and the Execute Query button

Read queries need no login (the DBpedia model), so applications can query it directly:

H=$(sudo grep '^VIRTUOSO_HOST=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
curl -s --cacert /etc/ssl/virtuoso/virtuoso.crt --resolve "$H:443:127.0.0.1" -H 'Accept: text/csv' \
  --data-urlencode 'query=SELECT ?s ?label WHERE { GRAPH <http://cloudimg.example/catalog> { ?s <http://www.w3.org/2000/01/rdf-schema#label> ?label } } ORDER BY ?s' \
  "https://$H/sparql"
"s","label"
"http://cloudimg.example/product/1","Virtuoso Open Source Edition"
"http://cloudimg.example/product/2","cloudimg AWS Marketplace image"

Anonymous updates are refused. INSERT, DELETE, LOAD and the Sponger need an authenticated account with SPARQL update rights:

H=$(sudo grep '^VIRTUOSO_HOST=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
curl -s --cacert /etc/ssl/virtuoso/virtuoso.crt --resolve "$H:443:127.0.0.1" \
  --data-urlencode 'query=INSERT DATA { GRAPH <http://example.org/g> { <http://example.org/s> <http://example.org/p> "x" } }' \
  "https://$H/sparql" | head -1
Virtuoso 42000 Error SR186:SECURITY: No permission to execute procedure DB.DBA.SPARQL_INSERT_DICT_CONTENT with user ID 107, group ID 107

If your data must not be public, allow TCP 443 only from your own networks in the security group, or remove the anonymous read grant in the Conductor (System Admin > User Accounts, user SPARQL).

Step 10: WebDAV

Virtuoso's WebDAV repository is at https://<public-dns>/DAV/. It refuses anonymous access and accepts the dav account with VIRTUOSO_DAV_PASSWORD:

H=$(sudo grep '^VIRTUOSO_HOST=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
DAV=$(sudo grep '^VIRTUOSO_DAV_PASSWORD=' /root/virtuoso-opensource-credentials.txt | cut -d= -f2-)
curl -s --cacert /etc/ssl/virtuoso/virtuoso.crt --resolve "$H:443:127.0.0.1" -u "dav:$DAV" -X PROPFIND -H 'Depth: 0' -o /dev/null -w 'dav: %{http_code}\n' "https://$H/DAV/"
curl -s --cacert /etc/ssl/virtuoso/virtuoso.crt --resolve "$H:443:127.0.0.1" -X PROPFIND -H 'Depth: 0' -o /dev/null -w 'anonymous: %{http_code}\n' "https://$H/DAV/"
dav: 207
anonymous: 401

Step 11: Reach the SQL port from your workstation

The SQL / ODBC / JDBC port stays on loopback. Forward it over SSH instead of opening it:

ssh -i my-key-pair.pem -L 1111:127.0.0.1:1111 ubuntu@<public-ip>

Then point a local isql, ODBC or JDBC client at 127.0.0.1:1111 with the dba account. For an application tier in the same VPC, open 1111 in the security group to that tier's subnet only and change ServerPort in /etc/virtuoso/virtuoso.ini to the private address.

Step 12: Instance metadata is blocked for Virtuoso

The virtuoso and nginx services carry a systemd rule that denies the instance metadata addresses, so a SPARQL LOAD, a Sponger fetch or http_get() can never read the instance's metadata or role credentials:

systemctl show -p IPAddressDeny virtuoso nginx
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32

IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32

From inside the Virtuoso service the metadata service does not answer (000):

sudo bash -c 'cg=$(systemctl show -p ControlGroup --value virtuoso.service); echo $$ > /sys/fs/cgroup$cg/cgroup.procs; curl -s -m 5 -o /dev/null -w "IMDS from virtuoso.service: %{http_code}\n" -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 60" http://169.254.169.254/latest/api/token' || true
IMDS from virtuoso.service: 000

Step 13: Use your own hostname and certificate

To serve Virtuoso under your own DNS name, point the name at the instance, then run:

sudo virtuoso-set-hostname <your-domain>

It records the name in /etc/cloudimg/virtuoso-hostname, issues a new self signed certificate for it, and reloads nginx. To use a certificate from your own CA, replace /etc/ssl/virtuoso/virtuoso.crt and /etc/ssl/virtuoso/virtuoso.key (keep the key mode 0600) and run sudo systemctl reload nginx.

Step 14: Manage the service

systemctl status virtuoso --no-pager | head -5
sudo journalctl -u virtuoso -n 20 --no-pager
  • Configuration: /etc/virtuoso/virtuoso.ini (restart with sudo systemctl restart virtuoso)
  • Database files: /var/lib/virtuoso/db (virtuoso.db, the transaction log virtuoso.trx and the server log virtuoso.log)
  • Back up with System Admin > Backup in the Conductor, or by stopping virtuoso and copying /var/lib/virtuoso/db
  • To change a password, run DB.DBA.USER_SET_PASSWORD('dba', '<new-password>'); in Interactive SQL or isql, then update the credentials file

Security notes

  • No credential is baked into the image. The image carries an inert template database that no instance ever serves. First boot copies it, sets dba and dav to per instance passwords, re-keys every other account, and only then starts Virtuoso and nginx.
  • Built in accounts other than dba and dav (SPARQL, SOAP, WebMeta and others) cannot log in.
  • nginx passes Virtuoso a fixed hostname and the real client address, overwriting any X-Forwarded-For a client sends.
  • AllowOSCalls = 0 and HTTPProxyEnabled = 0 are set in virtuoso.ini.
  • SSH host keys, the machine ID, the TLS key and every password are generated per instance.

Licensing and support

Virtuoso Open Source Edition is licensed under the GNU General Public License, version 2 (with OpenLink's OpenSSL and client driver exemptions). The image carries the unmodified official OpenLink 7.2.17 build; /opt/virtuoso/SOURCE.txt names the corresponding source. The commercial Virtuoso Enterprise Edition is a separate product and is not included. Virtuoso is a trademark of OpenLink Software; cloudimg is not affiliated with or endorsed by OpenLink Software.

cloudimg provides 24/7 support by email and live chat for every version in the listing: support@cloudimg.co.uk.