
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
- 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).
- 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:
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:
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
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
--server.username root --server.password Password
To further secure access, create a dedicated database and user:
javascript
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"
# Create certificate signing request (CSR) in file "server.csr"
# Copy away original private key to "server.key.org"
# Remove passphrase from the private key
# Sign the CSR with the key, creating certificate PEM file "server.crt"
# Combine certificate and key into single PEM file "server.pem"
3.2 Mount Certificates in Containers
Modify the docker-compose.yml file to include the certificate and key files:
Yaml
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
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
4.2 Scheduling Backups with cron
Automate daily backups at 2 AM:
bash
4.3 Restoring from Backup
Restore data using:
bash
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!
Get the latest tutorials, blog posts and news: