Safely Remove a Server from a 389 DS Replication Topology

Remove a consumer, hub, or supplier from a 389 Directory Server replication topology without losing updates, isolating replicas, or leaving stale RUV metadata.

Published

Updated

Read time 16 min read

Reviewed byDeepak Prasad

389 Directory Server remove replica from replication topology with dsconf agreements and CleanAllRUV

Removing a server from replication takes more than deleting one agreement. You drain client traffic, confirm updates reached every surviving replica, remove agreements on each peer, disable replication on the host you retire, and clean the supplier replica ID from the RUV when that host was a supplier. Skip a step and you can strand downstream consumers or leave stale metadata that blocks the next topology change.

This guide covers consumer, hub, and supplier removal on one suffix. For agreement work, see manage replication agreements. For supplier RUV cleanup, see CleanAllRUV. To compare two hosts before cutover, see ds-replcheck.

Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.


What removing a replica changes

Replication membership is suffix-specific. Repeat these steps for every replicated suffix on the instance you retire.

Action Scope Typical use
Delete one agreement One directional path on the server that owns the agreement Stop sending updates to one peer
Disable one agreement Same as delete, but reversible with repl-agmt enable Maintenance window on one hop
replication disable Entire suffix on one instance; removes local outgoing agreements for that suffix Detach a server from replication
Remove server from topology Agreements on all peers + disable replication + client/DNS updates (+ RUV cleanup for suppliers) Planned decommission
dsctl instance remove Deletes the local instance files Only after replication detachment

Deleting ldap1-to-hub1 on ldap1 does not remove hub1-to-branch1 on the hub or any agreement configured on another host. Supplier removal additionally requires CleanAllRUV when the supplier replica ID will not return.

Which steps apply by role

Step Consumer Hub Supplier
Drain application traffic Yes Yes Yes
Block new local writes Already read-only Already read-only Yes
Replace downstream paths No If applicable If applicable
Delete incoming agreements on peers Yes Yes Yes
Delete outgoing agreements on retiring host No If present If present
replication disable on retired host Yes Yes Yes
Record supplier replica ID No No Yes
CleanAllRUV No No Permanent removal only

Consumers and hubs do not need RUV cleanup because they do not hold a unique supplier replica ID for the suffix. Suppliers do. See replication architecture for how the RUV fits together.

IMPORTANT
dsconf replication disable is not the same as dsconf repl-agmt disable. Suffix-wide disable deletes local outgoing agreements for that suffix. Plan agreement changes before you disable replication on a hub that still forwards to branch consumers.

Plan the removal and map topology dependencies

Before you change production replication, capture what the topology looks like today.

On the server you plan to remove, and on every peer that replicates the suffix, run:

bash
dsconf -y /root/dm.pw ldap1 replication get --suffix "dc=example,dc=com"
bash
dsconf -y /root/dm.pw ldap1 repl-agmt list --suffix "dc=example,dc=com"
bash
dsconf -y /root/dm.pw ldap1 replication get-ruv --suffix "dc=example,dc=com"

Save repl-agmt get output for any agreement you might need to recreate during rollback. Take a backup of every instance you will touch before you delete agreements, disable replication, or remove an instance. Write down the replica role (nsDS5ReplicaType and nsDS5Flags), replica ID, every hostname and port clients use, and any downstream replicas that still depend on this server.

Select replacement replication paths

When you remove a hub or supplier, every remaining replica still needs a working upstream source before you delete the old path. If a hub forwards to branch consumers, create replacement agreements first and initialize them only when the branch is empty or you accept a total update. See cascading replication and initialize and reinitialize replicas.

The consumer, hub, and supplier sections below are separate exercises on the disposable bdb-consumer instance. Reset replication on bdb-consumer between exercises if you work through more than one scenario on the same host.


Lab environment

This guide uses disposable instances on one host. In production you use separate hosts, LDAPS, and hostnames that match your certificates.

Role Instance LDAP URL (lab) Replica ID Notes
Supplier ldap1 ldap://127.0.0.1:389 1 Keeps ldap1-to-supplier2 unchanged
Disposable target bdb-consumer ldap://127.0.0.1:21389 65535 / 3 when promoted Consumer and supplier removal exercises
Branch consumer bdb-lab ldap://127.0.0.1:20389 65535 Hub reroute example only
External supplier ldap2 on ldap2.example.com ldap://ldap2.example.com:1389 2 Final ds-replcheck online comparison target

Password files: /root/dm.pw (ldap1 and ldap2 Directory Manager in this lab), /root/hub1-dm.pw (bdb-consumer), /root/branch1-dm.pw (bdb-lab), /root/hub1-repl.pw, /root/ldap1-repl.pw.


Drain client traffic and replication updates

Pull the retiring server out of load balancers, application pools, and monitoring probes, even when it is a read-only consumer that still answers LDAP reads. Leave the instance running until pending updates have time to replicate.

On a supplier you plan to retire, stop new writes to that host. Backend read-only mode blocks LDAP modifications on one suffix without tearing down replication sessions:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer backend suffix set --enable-readonly userroot

Confirm the flag:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer backend suffix get userroot | grep -i readonly

Sample output:

output
nsslapd-readonly: on

Keep the suffix read-only until replication has caught up and you have disabled replication on the retiring host. Use backend suffix set --disable-readonly userroot only during rollback or after you isolate the detached instance for reuse. See read-only databases and instances for backend versus instance-wide read-only mode.

Check agreement health from the side that sends updates:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt status --suffix "dc=example,dc=com" --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/hub1-repl.pw ldap1-to-remove-consumer

When initialization succeeded, Last Init Status should end in Total update succeeded and Last Update Status in Incremental update succeeded. The 0 in Error (0) is only the LDAP result code. Read the full status line before you trust it.

For a quick lag check before you delete paths, ds-replcheck state compares replication state between two URLs:

bash
ds-replcheck state -m ldap://127.0.0.1:389 -r ldap://127.0.0.1:21389 -b "dc=example,dc=com" -D "cn=Directory Manager" -y /root/dm.pw

Sample output:

output
Replication State: Supplier and Replica are in perfect synchronization

state does not compare individual entries. Use the same Directory Manager password on both endpoints (/root/dm.pw in this lab), or bind with credentials that work on both replicas.


Remove a consumer from the topology

Use this path when the server is a read-only consumer (nsDS5ReplicaType: 2, nsDS5Flags: 0) and has no downstream replicas.

Delete agreements that point to the consumer

On every supplier that sends updates to the consumer, delete the outgoing agreement:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt delete --suffix "dc=example,dc=com" ldap1-to-remove-consumer

Sample output:

output
Agreement has been successfully deleted

Make sure no supplier still lists the consumer:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt list --suffix "dc=example,dc=com"

The retired agreement name should be gone. ldap1-to-supplier2 stays in this lab.

Disable replication on the consumer

After every incoming path is gone, disable replication on the consumer suffix:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication disable --suffix "dc=example,dc=com"

Sample output:

output
Replication disabled for "dc=example,dc=com"

Confirm the suffix no longer appears:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication list

Sample output:

output
There are no replicated suffixes

CleanAllRUV is not required. Consumers do not own a supplier replica ID. Test writes and reads through the remaining topology before you repurpose or delete the instance.


Remove a hub without isolating consumers

When you remove a hub, every consumer that only received updates through it needs a new upstream path first. Delete the hub agreements only after that path works.

This example uses ldap1bdb-consumer (hub) → bdb-lab (branch). Set up bdb-lab as a consumer on dc=example,dc=com and create ldap1-to-hub1 and hub1-to-branch1 before you start. See cascading replication.

Build and test the replacement path

Create a direct supplier-to-branch agreement on ldap1:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt create ldap1-to-branch1 --suffix "dc=example,dc=com" --host 127.0.0.1 --port 20389 --conn-protocol LDAP --bind-method SIMPLE --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/hub1-repl.pw

Initialize only when the branch consumer is empty or you accept a total update:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt init --suffix "dc=example,dc=com" ldap1-to-branch1

Confirm the direct agreement is healthy before you rely on it:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt status --suffix "dc=example,dc=com" --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/hub1-repl.pw ldap1-to-branch1

Sample output (trimmed):

output
Last Init Status: Error (0) Total update succeeded
Last Update Status: Error (0) Replica acquired successfully: Incremental update succeeded

While the old hub path is still up, ds-replcheck state cannot tell you whether the new direct agreement delivered a specific change. Temporarily disable hub forwarding, add a disposable write on ldap1, and confirm it reaches bdb-lab through ldap1-to-branch1 only:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt disable --suffix "dc=example,dc=com" hub1-to-branch1
bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=People,dc=example,dc=com
changetype: modify
add: description
description: remove-replica-hub-direct-check
EOF
bash
dsconf -y /root/dm.pw ldap1 repl-agmt poke --suffix "dc=example,dc=com" ldap1-to-branch1
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:20389 -D "cn=Directory Manager" -y /root/branch1-dm.pw -b "uid=user1,ou=People,dc=example,dc=com" -s base description

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com
description: remove-replica-hub-direct-check

The search should return the test description value. That confirms the direct path carried the update.

Remove the disposable value on ldap1, poke the direct agreement, and confirm description: remove-replica-hub-direct-check is gone on bdb-lab. Other description values on the entry can stay.

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=People,dc=example,dc=com
changetype: modify
delete: description
description: remove-replica-hub-direct-check
EOF
bash
dsconf -y /root/dm.pw ldap1 repl-agmt poke --suffix "dc=example,dc=com" ldap1-to-branch1
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:20389 \
  -D "cn=Directory Manager" -y /root/branch1-dm.pw \
  -b "uid=user1,ou=People,dc=example,dc=com" -s base \
  "(description=remove-replica-hub-direct-check)" dn

A successful deletion returns no output and exit status 0. Treat any LDAP bind, network, or search error as a failure. Do not continue until the command succeeds with an empty result.

Delete the old hub agreements in the next subsection.

Delete hub agreements and disable replication

After the replacement path is healthy, delete agreements that still point at the hub. Include hub1-to-branch1 if you disabled it while proving the direct path:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt delete --suffix "dc=example,dc=com" ldap1-to-hub1
bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt delete --suffix "dc=example,dc=com" hub1-to-branch1

Disable replication on the hub suffix:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication disable --suffix "dc=example,dc=com"

Sample output:

output
Replication disabled for "dc=example,dc=com"
WARNING
replication disable on the hub removes its local outgoing agreements for that suffix. Create and verify replacement paths before you disable replication on a hub that still forwards updates.

Remove a supplier safely

Retiring a supplier means draining writes, confirming every peer is caught up, removing agreements on each side, disabling replication on the host you retire, and running RUV cleanup when that supplier ID is gone for good.

This lab promotes disposable bdb-consumer to supplier replica ID 3, then removes it. IDs 1 and 2 belong to surviving suppliers and stay untouched.

Prepare the disposable supplier

Enable the consumer role and create an agreement from ldap1:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication enable --suffix "dc=example,dc=com" --role consumer --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/hub1-repl.pw
bash
dsconf -y /root/dm.pw ldap1 repl-agmt create ldap1-to-supplier3 --suffix "dc=example,dc=com" --host 127.0.0.1 --port 21389 --conn-protocol LDAP --bind-method SIMPLE --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/hub1-repl.pw

Sample output:

output
Successfully created replication agreement "ldap1-to-supplier3"

Initialize the disposable supplier:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt init --suffix "dc=example,dc=com" ldap1-to-supplier3

Poll until initialization completes:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt init-status --suffix "dc=example,dc=com" ldap1-to-supplier3

Sample output:

output
Agreement successfully initialized.

Promote to supplier with an unused replica ID:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication promote --suffix "dc=example,dc=com" --newrole supplier --replica-id 3

Sample output:

output
Successfully promoted replica to "supplier"

Check the supplier role and replica ID:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication get --suffix "dc=example,dc=com" | grep -E 'nsDS5Replica(Id|Type)'

Sample output:

output
nsDS5ReplicaId: 3
nsDS5ReplicaType: 3

For multi-supplier layouts, add the return agreement from the retiring supplier back to its peers. Do not initialize the peer that already holds the data. Red Hat's procedure expects the reverse agreement to complete an incremental update on its own. See multi-supplier replication.

Create the return agreement:

bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt create supplier3-to-ldap1 --suffix "dc=example,dc=com" --host 127.0.0.1 --port 389 --conn-protocol LDAP --bind-method SIMPLE --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/ldap1-repl.pw

Sample output:

output
Successfully created replication agreement "supplier3-to-ldap1"

If repl-agmt status complains that no changelog is available, check the error log on that host. On my 389 DS 3.2.0 lab I cleared it with a controlled restart, then recreated and poked the return agreement. Treat a restart as a last resort in production until you know why the changelog was not ready:

bash
dsctl bdb-consumer restart

Sample output:

output
Instance "bdb-consumer" has been restarted

Recreate the return agreement if you deleted it during troubleshooting, then continue with the bidirectional test below.

Prove bidirectional replication before you retire the supplier. Add a disposable write on supplier 3, poke the return agreement, and confirm the value shows up on ldap1:

bash
ldapmodify -x -H ldap://127.0.0.1:21389 -D "cn=Directory Manager" -y /root/hub1-dm.pw <<'EOF'
dn: uid=user1,ou=People,dc=example,dc=com
changetype: modify
add: description
description: remove-replica-supplier3-check
EOF
bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt poke --suffix "dc=example,dc=com" supplier3-to-ldap1
bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt status --suffix "dc=example,dc=com" --bind-dn "cn=replication manager,cn=config" --bind-passwd-file /root/ldap1-repl.pw supplier3-to-ldap1

Sample output (trimmed):

output
Last Update Status: Error (0) Replica acquired successfully: Incremental update succeeded
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user1,ou=People,dc=example,dc=com" -s base description

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com
description: remove-replica-supplier3-check

Last Update Status should end in Incremental update succeeded. If you see a changelog or incremental failure, stop here. Do not retire the supplier until the return agreement reports a successful incremental update. On my lab a controlled restart cleared a transient error, but check your changelog configuration and logs before you rely on that in production.

Remove the test value and poke the agreement again before you delete paths:

bash
ldapmodify -x -H ldap://127.0.0.1:21389 -D "cn=Directory Manager" -y /root/hub1-dm.pw <<'EOF'
dn: uid=user1,ou=People,dc=example,dc=com
changetype: modify
delete: description
description: remove-replica-supplier3-check
EOF
bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt poke --suffix "dc=example,dc=com" supplier3-to-ldap1
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 \
  -D "cn=Directory Manager" -y /root/dm.pw \
  -b "uid=user1,ou=People,dc=example,dc=com" -s base \
  "(description=remove-replica-supplier3-check)" dn

A successful deletion returns no output and exit status 0. Other description values on the entry do not affect this check. The filter matches only remove-replica-supplier3-check.

Record the supplier replica ID

Before you disable replication on the supplier, note its replica ID and confirm it appears in the RUV on a surviving supplier. I captured the block below after the test add and deletion above:

bash
dsconf -y /root/dm.pw ldap1 replication get-ruv --suffix "dc=example,dc=com"

Sample output from this lab (trimmed):

output
RUV:        {replica 3 ldap://ldap1.example.com:21389} 6a5d064c000000030000 6a5d064e000000030000
Replica ID: 3
LDAP URL:   ldap://ldap1.example.com:21389
Min CSN:    2026-07-19 17:15:56 (6a5d064c000000030000)
Max CSN:    2026-07-19 17:15:58 (6a5d064e000000030000)

You need replica ID 3 for CleanAllRUV. In a single-host lab the RUV LDAP URL may show ldap1.example.com even when you manage the instance as bdb-consumer. Use the replica ID, not the URL hostname, when you plan cleanup.

Delete agreements and disable replication

Delete agreements on peers first, then disable replication on the retired supplier:

bash
dsconf -y /root/dm.pw ldap1 repl-agmt delete --suffix "dc=example,dc=com" ldap1-to-supplier3
bash
dsconf -y /root/hub1-dm.pw bdb-consumer repl-agmt delete --suffix "dc=example,dc=com" supplier3-to-ldap1
bash
dsconf -y /root/hub1-dm.pw bdb-consumer replication disable --suffix "dc=example,dc=com"

Each delete should report Agreement has been successfully deleted. Disable should report Replication disabled for "dc=example,dc=com".

Confirm another supplier still accepts writes and reaches every remaining replica before you run RUV cleanup.


Clean the removed supplier's RUV

Run CleanAllRUV only when the supplier is permanently removed and its replica ID will not come back on the same server identity. Start the task from one surviving supplier while every replica you need for cleanup is online.

bash
dsconf -y /root/dm.pw ldap1 repl-tasks cleanallruv --suffix "dc=example,dc=com" --replica-id 3

Sample output:

output
Created task cleanallruv_2026-07-19T20:48:17.000687

Monitor progress on the supplier that started the task:

bash
dsconf -y /root/dm.pw ldap1 repl-tasks list-cleanruv-tasks

Sample output when the task completes:

output
dn: cn=cleanallruv_2026-07-19T20:48:17.000687,cn=cleanallruv,cn=tasks,cn=config
cn: cleanallruv_2026-07-19T20:48:17.000687
nsTaskStatus: Successfully cleaned rid(3)
replica-id: 3

Verify replica ID 3 no longer appears in the RUV on every surviving replica. Check suppliers, hubs, and consumers that remain online:

bash
dsconf -y /root/dm.pw ldap1 replication get-ruv --suffix "dc=example,dc=com"
bash
dsconf -y /root/dm.pw ldap://ldap2.example.com:1389 replication get-ruv --suffix "dc=example,dc=com"

After cleanup on ldap1 and ldap2, only surviving supplier identities should remain. In this lab that means IDs 1 and 2.

For task monitoring, abort procedures, --force-cleaning, and offline-replica risks, see CleanAllRUV. For recovery after a partial cleanup, see restore a replicated server.


Check the remaining replication topology

When removal and RUV cleanup are done, check the following:

  • No agreement lists the retired hostname or port.
  • The retired supplier ID is absent from the RUV on every surviving replica.
  • repl-agmt status reports successful incremental updates on remaining paths.
  • A test write on the primary supplier replicates to every consumer you still serve.
  • Access and error logs show no repeated connection failures to the retired host.
  • DNS, certificates, load balancers, and monitoring target surviving instances only.

Run ds-replcheck online when you need entry-level comparison between surviving hosts. In this lab, /root/dm.pw works on both ldap1 and ldap2:

bash
ds-replcheck online -D "cn=Directory Manager" -y /root/dm.pw -m ldap://127.0.0.1:389 -r ldap://ldap2.example.com:1389 -b "dc=example,dc=com"

Sample output (trimmed):

output
Result
```output
=====================================================

No replication differences between Supplier and Replica

Use ds-replcheck state only for a lightweight replication-state or lag check. It is not entry-level proof. See Comparing two Directory Server instances.


Remove or repurpose the local instance

dsctl instance_name remove --do-it deletes the instance only after replication is disabled and no peer still expects updates from that server identity. Removing the instance does not clean agreements on remote hosts or RUV entries on suppliers.

If you keep the instance for lab work, disable replication, isolate it from production clients, and make sure it cannot rejoin the topology with a stale supplier ID. A server that returns after CleanAllRUV should be treated as a new replica. Assign an unused supplier ID and reinitialize. See initialize and reinitialize replicas.

dsctl remove is not a substitute for replication disable and agreement cleanup on peers.


Rollback and common removal problems

Rollback is straightforward before CleanAllRUV. Restore agreements from saved repl-agmt get output, reinitialize only when required, and verify both directions. After RUV cleanup, treat the returning server as a new replica with a new or previously cleaned supplier ID.

Symptom Likely cause Fix
Downstream consumer stopped updating Hub or supplier removed before replacement path worked Restore or create upstream agreement; initialize if required
replication disable deleted hub forwarding Disabled replication on hub while branch still depended on it Reroute branch consumers first; see hub removal section
CleanAllRUV task waits indefinitely Required replica offline Bring every peer online or follow forced-cleanup guidance in CleanAllRUV
Wrong replica ID cleaned Recorded ID from wrong suffix or stale get-ruv Confirm ID with replication get and RUV on an authoritative supplier before cleanup
Clients still hit retired host DNS or load balancer not updated Update service discovery and health checks
Can't acquire replica during init Consumer role missing or wrong suffix on destination Enable consumer on the suffix; confirm backend exists. See initialize replicas
Changelog or incremental failure on return agreement Reverse agreement created before supplier changelog is ready, or agreement disabled Confirm Incremental update succeeded. On my 389 DS 3.2.0 lab a controlled restart cleared a transient error. Check changelog configuration and logs before you rely on that in production. See multi-supplier replication
Agreement gone but server still replicates Only deleted one directional path Inspect agreements on every peer; agreements are directional

For failed or permanently unreachable suppliers, see restore a replicated server and replication troubleshooting in the product documentation.


References


Summary

Match the workflow to the role: drain application traffic, delete peer agreements, disable suffix replication on the retired host, and run CleanAllRUV only after permanent supplier removal. Replace hub paths before you disable a forwarding hub. Use ds-replcheck state for quick lag checks and ds-replcheck online when you need entry-level comparison. Check the surviving topology before you delete the instance or update production routing.


Frequently Asked Questions

1. Do I need CleanAllRUV when removing a consumer or hub?

No. CleanAllRUV applies only when a supplier replica ID is permanently retired. Consumers and hubs use the reserved read-only ID 65535 and do not originate supplier updates that remain in the RUV.

2. What is the difference between deleting an agreement and disabling replication?

Deleting an agreement removes one directional replication path on the server where you run the command. Disabling replication on a suffix removes that server from replication for the suffix and deletes its local outgoing agreements for that suffix.

3. Can I reuse a supplier replica ID immediately after demotion?

Temporary demotion does not free the replica ID; keep it reserved for the same server identity. Before assigning it to a different server after permanent removal, complete CleanAllRUV and verify the ID is absent from every surviving RUV.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …