home shape

Deploying and Securing an ArangoDB Cluster Using Docker

Introduction

Deploying a distributed database securely can be challenging, but Docker simplifies the process. This guide walks you through setting up a three-node ArangoDB cluster using Docker and Docker Compose. I'll also cover essential security measures, including authentication, TLS encryption, and automated backups.

Before You Begin

  1. Create a Folder: Create a dedicated folder on your system where you will store all the files related to this setup (e.g., arangodb-cluster).
  2. Open Terminal in the Folder: Open your terminal and navigate to the folder you just created. All commands in this guide should be run from this folder.

1. Setting Up the Cluster

1.1 Prerequisites

Before you begin, ensure that your system has the following installed:

  • Docker — for containerized deployment.
  • Docker Compose — for managing multi-container applications.
  • OpenSSL — for generating TLS certificates.

1.2 Creating a Docker Network

Create a dedicated Docker network to ensure secure communication between cluster nodes:

Bash:

docker network create arangodb-net

1.3 Create .env File

Create a .env file to store sensitive information such as the JWT secret key and the ArangoDB root password:

ARANGO_ROOT_PASSWORD=Password

ARANGO_JWT_SECRET=Z3uM7z+WkP1r8UxvOZkQ+v4R4dGFL9aA+dmby5Z1R5c=

1.4 Deploying the Cluster

Define the cluster in a docker-compose.yml file:

networks:
  default:
    name: arangodb-net
    external: trueservices:
  agency1:
    image: arangodb/enterprise:3.12.4
    container_name: agency1
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8531
      --agency.activate true
      --agency.size 3
      --agency.supervision true
      --server.authentication true
      --agency.endpoint tcp://agency1:8531
      --agency.endpoint tcp://agency2:8531
      --agency.endpoint tcp://agency3:8531
      --agency.my-address=tcp://agency1:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default
    healthcheck:
      test: ["CMD", "sh", "-c", "arangosh --server.endpoint tcp://agency1:8531 --server.authentication true --server.username root --server.password $$ARANGO_ROOT_PASSWORD --javascript.execute 'db._query(\"RETURN 1\").toArray()'"]
      interval: 10s
      timeout: 10s
      retries: 10  agency2:
    image: arangodb/enterprise:3.12.4
    container_name: agency2
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8531
      --agency.activate true
      --agency.size 3
      --agency.supervision true
      --server.authentication true
      --agency.endpoint tcp://agency1:8531
      --agency.endpoint tcp://agency2:8531
      --agency.endpoint tcp://agency3:8531
      --agency.my-address=tcp://agency2:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default

  agency3:
    image: arangodb/enterprise:3.12.4
    container_name: agency3
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8531
      --agency.activate true
      --agency.size 3
      --agency.supervision true
      --server.authentication true
      --agency.my-address=tcp://agency3:8531
      --agency.endpoint tcp://agency1:8531
      --agency.endpoint tcp://agency2:8531
      --agency.endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default

  dbserver1:
    image: arangodb/enterprise:3.12.4
    container_name: dbserver1
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8530
      --cluster.my-address tcp://dbserver1:8530
      --cluster.my-role DBSERVER
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default

  dbserver2:
    image: arangodb/enterprise:3.12.4
    container_name: dbserver2
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8530
      --cluster.my-address tcp://dbserver2:8530
      --cluster.my-role DBSERVER
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default

  dbserver3:
    image: arangodb/enterprise:3.12.4
    container_name: dbserver3
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8530
      --cluster.my-address tcp://dbserver3:8530
      --cluster.my-role DBSERVER
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default

  coordinator1:
    image: arangodb/enterprise:3.12.4
    container_name: coordinator1
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8529
      --cluster.my-address tcp://coordinator1:8529
      --cluster.my-role COORDINATOR
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default
    ports:
      - "8541:8529"

  coordinator2:
    image: arangodb/enterprise:3.12.4
    container_name: coordinator2
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8529
      --cluster.my-address tcp://coordinator2:8529
      --cluster.my-role COORDINATOR
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default
    ports:
      - "8551:8529"

  coordinator3:
    image: arangodb/enterprise:3.12.4
    container_name: coordinator3
    command: >
      /bin/sh -c "arangod
      --server.endpoint tcp://0.0.0.0:8529
      --cluster.my-address tcp://coordinator3:8529
      --cluster.my-role COORDINATOR
      --server.authentication true
      --cluster.agency-endpoint tcp://agency1:8531
      --cluster.agency-endpoint tcp://agency2:8531
      --cluster.agency-endpoint tcp://agency3:8531
      --server.jwt-secret $$ARANGO_JWT_SECRET"
    environment:
      - ARANGO_ROOT_PASSWORD=${ARANGO_ROOT_PASSWORD}
      - ARANGO_JWT_SECRET=${ARANGO_JWT_SECRET}
    networks:
      - default
    ports:
      - "8561:8529"

 

Start the cluster with the following command:

bash

docker compose --env-file .env up -d

 

This command starts all containers in detached mode. You can access the ArangoDB web interface via the following URLs:

  • Coordinator1: http://localhost:8541
  • Coordinator2: http://localhost:8551
  • Coordinator3: http://localhost:8561

2. Authentication and User Management

 
By default, ArangoDB allows root access. To enhance security, set a strong root password and create additional users with restricted privileges.

2.1 Creating a New User

Execute the following command to create a new user:

bash

docker exec -it coordinator1 arangosh --server.endpoint http+tcp://coordinator1:8529 \
--server.username root --server.password Password

 
To further secure access, create a dedicated database and user:

javascript

db._createDatabase("secureDB");
db._createUser("adminUser", "StrongPassword", { active: true });

3. Enabling TLS/SSL Encryption

Secure communication between nodes with TLS encryption.

3.1 Generate Certificates

Use OpenSSL to generate a private key, certificate signing request (CSR), and a self-signed certificate:

# Create private key in file "server.key"

span style="font-weight: 400;">openssl genpkey -out server.key -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-128-cbc

 
# Create certificate signing request (CSR) in file "server.csr"

openssl req -new -key server.key -out server.csr

 
# Copy away original private key to "server.key.org"

cp server.key server.key.org

 
# Remove passphrase from the private key

openssl rsa -in server.key.org -out server.key

 
# Sign the CSR with the key, creating certificate PEM file "server.crt"

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

 
# Combine certificate and key into single PEM file "server.pem"

cat server.crt server.key > server.pem

3.2 Mount Certificates in Containers

Modify the docker-compose.yml file to include the certificate and key files:

Yaml

coordinator1:
  volumes:
    - ./server.pem:/etc/arangodb3/keyfile.pem
coordinator2:
  volumes:
    - ./server.pem:/etc/arangodb3/keyfile.pem
coordinator3:
  volumes:
    - ./server.pem:/etc/arangodb3/keyfile.pem

3.3 Restart the Cluster

Apply the configuration by restarting the cluster:
bash

docker-compose restart

4. Backup and Recovery

Regular backups ensure data safety and quick recovery in case of failures.

4.1 Automating Backups with arangodump

Perform manual backups with:

bash

docker exec coordinator1 arangodump --output-directory /backups --server.password Password

 

4.2 Scheduling Backups with cron

Automate daily backups at 2 AM:

bash

docker exec coordinator1 sh -c "echo '0 2 * * * arangodump --output-directory /backups --server.password Password' | crontab -"

 

4.3 Restoring from Backup

Restore data using:
bash

docker exec coordinator1 arangorestore --input-directory /backups

 

Conclusion

By following this guide, you have successfully deployed a secure, scalable ArangoDB cluster using Docker. This setup includes authentication, encrypted connections, and automated backups to ensure high availability and data protection. Your ArangoDB cluster is now production-ready!

Ubaid Khan

Leave a Comment





Get the latest tutorials, blog posts and news: