﻿---
path: faq/docker/fault-tolerance/replica-set-install.mdx
title: Installation with a pre-configured replica set
slug: replica-set-install
description: >-
  Configuring a MongoDB replica set during a fresh Passwork installation in
  Docker: preparing three servers, the keyfile, rs0 initialization, and
  configuring Passwork to connect to the replica set.
keywords:
  - Passwork
  - Docker
  - Replica Set
  - MongoDB
  - fault tolerance
  - clean installation
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

:::danger
MongoDB replication requires at least **three servers**.
:::

## Overview

An example of configuring a MongoDB replica set when Passwork is not in use yet and fault tolerance has to be set up from the start.

The following host names are used as an example:

- First server (PRIMARY) — **example.docker.1**
- Second server (SECONDARY) — **example.docker.2**
- Third server (SECONDARY) — **example.docker.3**

## Preparing the servers

:::danger
These steps are performed on **every** server: example.docker.1, example.docker.2, example.docker.3.
:::

### Installing Docker

1. Download and install Docker. The minimum version is 18.06.0.  
   Official article: [installing Docker](https://docs.docker.com/engine/installation/).
2. Install and enable the Docker Compose plugin if required.  
   Official article: [installing Docker Compose (Linux)](https://docs.docker.com/compose/install/linux/).

:::warning
We recommend using a Docker installation that was **not** made through snap.
:::

### Installing Passwork

Create a directory for the installation and change into it:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
mkdir /<passwork>/ && cd /<passwork>/
```

  </TabItem>
</Tabs>

Download the docker-compose build archive and extract it:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
curl -SfL https://repos.passwork.pro/repository/passwork-docker/passwork_compose_last.tar.gz | tar xzvf - 2>&1
rm -f passwork_compose_last.tar.gz
```

  </TabItem>
</Tabs>

Rename the environment variables configuration file:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
mv ./.env.example ./.env
```

  </TabItem>
</Tabs>

Edit the `.env` file:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
vim ./.env
```

  </TabItem>
</Tabs>

- Put the API key from the [Customer Portal](https://portal.passwork.pro) into the `PORTAL_KEY` line:

<ImageComponent
  src={'/img/assets/faq-docker-replica-set-install-apikey.png'}
  alt="The API key in the Customer Portal"
  format='regular'
/>

- At the end of the variables file, insert the following lines and specify your own values:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
# Database user name used at initialization.
MONGO_INITDB_ROOT_USERNAME=username
# Database user password used at initialization.
MONGO_INITDB_ROOT_PASSWORD=password
# DNS name or IP address of the host where the database is installed
MONGO_NODE_NAME="example.docker.2(3)"
# Flags the database is started with
DB_RUN_FLAGS="--replSet rs0 --keyFile=/data/keys/keyfile"
```

  </TabItem>
</Tabs>

Run the script that downloads the Passwork code and places it into the Docker build:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
cd /<passwork>/ && ./update.sh
```

  </TabItem>
</Tabs>

## Preparing the environment

:::danger
These steps are performed on **every** server: example.docker.1, example.docker.2, example.docker.3.
:::

Edit the Docker container configuration file `/<passwork>/docker-compose.yaml`:

- Uncomment the `ports` parameter and its value in the `db` service:

```yaml
ports:
  - 27017:27017
```

:::info
Forwarding the port from the container to the host is required for access and data exchange between the database instances.
:::

### Generating and configuring the replica set key

Create the `mongo` directory on **every** server:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
mkdir -p /<passwork>/conf/mongo
```

  </TabItem>
</Tabs>

On **example.docker.1**, generate the key for the replica set:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
openssl rand -base64 756 > /<passwork>/conf/mongo/keyfile
```

  </TabItem>
</Tabs>

The key file is used inside the replica set to authorize the nodes. If the file is not specified or its permissions are broader than **0400**, the replica set will not assemble correctly.

Copy the key to the secondary servers:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
scp /<passwork>/conf/mongo/keyfile username@example.docker.2:/<passwork>/conf/mongo/
scp /<passwork>/conf/mongo/keyfile username@example.docker.3:/<passwork>/conf/mongo/
```

  </TabItem>
</Tabs>

Set the permissions on **every** server:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
chown 1001:1001 /<passwork>/conf/mongo/keyfile
chown 1001:1001 /<passwork>/conf/mongo/
chmod 0700 /<passwork>/conf/mongo/
chmod 0400 /<passwork>/conf/mongo/keyfile
```

  </TabItem>
</Tabs>

## Configuring the replica set

### Starting the containers

:::warning
If DNS is not configured, add the records to `/etc/hosts` on every node:
- 172.16.X.X example.docker.1
- 172.16.X.X example.docker.2
- 172.16.X.X example.docker.3
:::

Start the Docker containers on every server:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
cd /<passwork>/
docker compose up -d
```

  </TabItem>
</Tabs>

Connect to the MongoDB shell on **example.docker.1**:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
docker exec -it passwork_db mongosh -u username -p password
```

  </TabItem>
</Tabs>

Switch to the `admin` database:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
use admin
```

  </TabItem>
</Tabs>

Initialize the replica set named `rs0`:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
rs.initiate( {
   _id : "rs0",
   members: [
      { _id: 0, host: "example.docker.1:27017" },
      { _id: 1, host: "example.docker.2:27017" },
      { _id: 2, host: "example.docker.3:27017" }
   ]
})
```

  </TabItem>
</Tabs>

Check the status:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
rs.status()
```

  </TabItem>
</Tabs>

## Configuring Passwork to connect to the replica set

### Configuring the primary server

Connect to the Passwork web interface on the first node. At step 3 of the checklist, specify the connection to the PRIMARY node — **example.docker.1**:

<ImageComponent
  src={'/img/assets/faq-docker-replica-set-install-checkshot.png'}
  alt="Connecting to the PRIMARY node in the checklist"
  format='regular'
/>

Specify the connection string:

```text
mongodb://username:password@example.docker.1:27017
```

Click **Next** and complete the Passwork installation. The `/<passwork>/conf/keys/config.env` configuration file will be generated. Edit it and specify the replica set connection:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
MONGODB_URL=mongodb://example.docker.1:27017,example.docker.2:27017,example.docker.3:27017/?replicaSet=rs0
MONGODB_DB=pw
MONGODB_USERNAME=username
MONGODB_PASSWORD=password
```

  </TabItem>
</Tabs>

### Configuring the secondary servers

Copy the generated configuration file `config.env` and the `encryption_key` from `example.docker.1` to the secondary servers:

<Tabs className="tabs-container">
  <TabItem className="tab-item-container" value="shell" label="shell">

```bash
scp /<passwork>/conf/keys/config.env username@example.docker.2:/<passwork>/conf/keys/
scp /<passwork>/conf/keys/config.env username@example.docker.3:/<passwork>/conf/keys/
scp /<passwork>/conf/keys/encryption_key username@example.docker.2:/<passwork>/conf/keys/
scp /<passwork>/conf/keys/encryption_key username@example.docker.3:/<passwork>/conf/keys/
```

  </TabItem>
</Tabs>

On all three nodes, edit the `APP_URL` parameter in the configuration and specify the DNS name or IP address of the server.
