feat: more operator guide

This commit is contained in:
Iain Learmonth 2025-11-09 14:39:28 +00:00
parent 8f7d0d372e
commit e72c729735
13 changed files with 240 additions and 7 deletions

View file

@ -0,0 +1,5 @@
---
label: Admin Guide
position: 30
link:
type: "generated-index"

5
docs/admin/intro.md Normal file
View file

@ -0,0 +1,5 @@
# Introduction
:::warning[Under construction]
This documentation is a work in progress. Please [get in touch with us](mailto:help@cdr.link) if you have any questions.
:::

View file

@ -0,0 +1,5 @@
---
label: Agent Guide
position: 20
link:
type: "generated-index"

5
docs/agent/intro.md Normal file
View file

@ -0,0 +1,5 @@
# Introduction
:::warning[Under construction]
This documentation is a work in progress. Please [get in touch with us](mailto:help@cdr.link) if you have any questions.
:::

View file

@ -5,3 +5,6 @@ sidebar_label: Overview
# Documentation Overview # Documentation Overview
:::warning[Under construction]
This documentation is a work in progress. Please [get in touch with us](mailto:help@cdr.link) if you have any questions.
:::

View file

@ -1,4 +1,5 @@
--- ---
label: Operator Guide label: Operator Guide
position: 40
link: link:
type: "generated-index" type: "generated-index"

View file

@ -20,7 +20,9 @@ network namespaces.
Both Both
[discretionary access controls](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/managing-file-system-permissions_configuring-basic-system-settings) [discretionary access controls](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/managing-file-system-permissions_configuring-basic-system-settings)
and SELinux are used to prevent lateral movement between containers should a container be compromised, with particular and
[SELinux](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/using_selinux/index)
are used to prevent lateral movement between containers should a container be compromised, with particular
attention given to the messaging channels WhatsApp and Signal. attention given to the messaging channels WhatsApp and Signal.
No container runs its application as the inside "root" user, which is an unprivileged user on the host. No container runs its application as the inside "root" user, which is an unprivileged user on the host.
@ -33,7 +35,7 @@ prevent later investigation, and automatically shut down instances where there i
## Components ## Components
The following diagram shows the dependency relationships between the components of CDR Link. The following diagram shows the dependency relationships between the components of CDR Link.
If you use our [Ansible role](./deploy) for deployment then these will be automatically configured. If you use our [Ansible role](./deploy.md) for deployment then these will be automatically configured.
The Link stack containers are The Link stack containers are
[OCI](https://opencontainers.org/) compliant containers and you can run these with alternatives [OCI](https://opencontainers.org/) compliant containers and you can run these with alternatives
such as [Docker Compose](https://docs.docker.com/compose/) however we would not be able to provide support for this such as [Docker Compose](https://docs.docker.com/compose/) however we would not be able to provide support for this
@ -48,8 +50,8 @@ The service definitions are in `.container` units within the Quadlet directory a
```mermaid ```mermaid
flowchart TD flowchart TD
bridge-worker.service --> bridge-postgresql.service bridge-worker.service --> bridge-postgresql.service
bridge-worker.service --> bridge-whatsapp.service bridge-worker.service -.-> bridge-whatsapp.service
bridge-worker.service --> signal-cli-rest-api.service bridge-worker.service -.-> signal-cli-rest-api.service
link.service --> bridge-postgresql.service link.service --> bridge-postgresql.service
link.service --> bridge-worker.service link.service --> bridge-worker.service

View file

@ -0,0 +1,70 @@
---
sidebar_position: 30
sidebar_label: Deployment Host
---
# Deployment Host Setup
Deployment takes place using [Ansible](https://docs.ansible.com/) which we will install in a
[venv](https://docs.python.org/3/library/venv.html) to allow for careful management of the versions of the software in
use.
For security, the deployment host must not run any network services listening on an external interface other than a
hardened SSH daemon if being used remotely. Ideally, the deployment host is operated locally via its terminal.
Begin by creating a directory for the deployment framework to operate from that should be owned by your unprivileged
user and group and have filesystem permissions of `0700`.
On systems with SELinux, a context of `user_home_t` should be appropriate.
This documentation will assume that you are working in the directory `$HOME/ops/`.
## Virtual Environment Setup
Begin by creating and activating a virtual environment:
```shell
cd $HOME/ops
python3 -m venv venv
source venv/bin/activate
```
Then install the dependencies we will require:
```shell
pip install ansible
pip install bitwarden-sdk # optional: only required for bitwarden secrets manager
```
## Install the Ansible collection and role dependencies
Create `$HOME/ops/requirements.yml`:
```yaml
---
collections:
- name: bitwarden.secrets # optional: only required for bitwarden secrets manager
- src: git+https://guardianproject.dev/sr2/ansible-collection-core.git
version: main # optional: only required for our baseline role
- src: git+https://guardianproject.dev/sr2/ansible-collection-apps.git
version: main # required: contains the CDR Link deployment role
roles:
- src: git+https://github.com/ansible-lockdown/RHEL9-CIS.git
version: "2.0.3" # optional: only required for our baseline role
```
Install the collections, and roles if required:
```shell
cd $HOME/ops
ansible-galaxy collection install -r requirements.yml
ansible-galaxy role install -r requirements.yml
```
## Create deployment data files and directories
Create the necessary directories that we will need in the next step:
```shell
cd $HOME/ops
mkdir {host,group}_vars
```

64
docs/operator/deploy.md Normal file
View file

@ -0,0 +1,64 @@
---
sidebar_position: 50
sidebar_label: Deploy CDR Link
---
# Deploy the CDR Link Stack
## Set up the Ansible inventory and host variables
Create `$HOME/ops/inventory`:
```ini
[cdr_link]
example.cdr.link
```
Create `$HOME/ops/group_vars/all.yml` if you use our baseline role and integrate with Identity Management:
```yaml
---
ipaserver_domain: CHANGEME
ipaserver_realm: CHANGEME
ipaserver_netbios_name: CHANGEME
```
Create `$HOME/ops/host_vars/example.cdr.link.yml`:
```yaml
---
baseline_second_disk_device: /dev/sdb # This is the device path for the data volume
baseline_home_luks_passphrase: CHANGEME
ipaclient_otp: CHANGEME # This is the OTP generated in the IdM step and is not sensitive after use
podman_link_podman_rootless_user: link_example # This is the user you created in the IdM step
podman_link_postgres_zammad_password: CHANGEME
podman_link_postgres_link_password: CHANGEME
podman_link_postgres_root_password: CHANGEME
podman_link_zammad_redis_password: CHANGEME
podman_link_opensearch_password: CHANGEME
podman_link_nextauth_secret: CHANGEME
```
:::warning
Do not store sensitive values in the `host_vars` file in plaintext, use lookup plugins to look up the secret values
using your secrets management solution of choice.
:::
The variables prefixed with `baseline_` and `ipaclient_` are only applicable if you are using our baseline role with
Identity Management integration.
If you manage your own hardening and use local users and groups you can omit these.
The user you reference in `podman_link_podman_rootless_user` must exist before continuing.
## Execute the Ansible playbook
If you are using our baseline role:
```shell
ansible-playbook -i inventory sr2.apps.link
```
If you manage your own hardening and identity management, use the `link` tag to only run the CDR Link stack deployment:
```shell
ansible-playbook -i inventory sr2.apps.link --tags link
```

73
docs/operator/identity.md Normal file
View file

@ -0,0 +1,73 @@
---
sidebar_position: 40
sidebar_label: Identity Management
---
# Identity Management Setup
:::tip
If you are using an alternative Identity Management system or local user accounts, skip this page and go straight
to [Deploying with Ansible](./deploy.md).
:::
## Host Setup
It can be helpful to keep track of the following information in a text editor's buffer until deployment is complete.
None of these details are sensitive after the completion of the deployment.
```text
Hostname:
IPv4 Address:
IPv6 Address:
OTP:
```
### Add Host to DNS
1. Create an A record for the host
1. Create an AAAA record for the host
1. Create a null MX record for the host (e.g. `example.cdr.link IN MX 0 .`)
### Add Host to Identity Management
1. Begin by logging in to the Identity Management server with your privileged identity
1. Open the **Identity** tab, and select the **Hosts** subtab
1. Click **Add** at the top of the hosts list
1. Enter the name of the new host, e.g. `example.cdr.link`
1. The IP address will be automatically resolved from DNS, you can leave this blank but may need to allow a moment for
the authoritative DNS servers to update
1. Activate the **Generate OTP** checkbox
1. Click **Add** to add the new host
1. Save the generated OTP for later
![Screenshot of the Add Host Wizard in Identity Management](/img/host-add.png)
## User Setup
### Create the Service User
This is the user on the host that will run the Podman containers.
1. Open the **Identity** tab, and select the **Users** subtab
1. Click **Add** at the top of the users list
1. Enter a **Username**, we prefix all our Link service users with `link_` for easy identification
1. Enter a **First Name** and **Last Name**, these values do not matter but the LDAP schema requires them
1. Do not enter a **New Password** as this user will never need to authenticate with a password
1. Click **Add**
![Screenshot of the Add User Wizard in Identity Management](/img/user-add.png)
### Generate subordinate IDs for the user
1. Open the **Identity** tab, and expand the **Subordinate IDs** subtab
1. Choose the **Subordinate IDs** option from the drop-down menu
1. Click the **Add** button in the upper-right corner of the interface
1. In the **Add subid** window, select the user you have just created as the **Owner**
1. Click **Add**
The range is automatically generated and managed by Identity Management.
:::tip
If you are not using our baseline Ansible role, ensure that the `with-subid` feature of the `sssd` authselect profile is
enabled to allow hosts to look up subids in LDAP.
:::

View file

@ -19,9 +19,9 @@ A compromise of this host effectively compromises the entire stack.
* Appropriately hardened and vendor supported Linux operating system with the latest security updates applied * Appropriately hardened and vendor supported Linux operating system with the latest security updates applied
* SSH key backed by hardware security module and requiring unlock (e.g. [YubiKey](https://www.yubico.com/)) to be used * SSH key backed by hardware security module and requiring unlock (e.g. [YubiKey](https://www.yubico.com/)) to be used
for login to the instance host for login to the instance host
* Python 3.11+ (the `venv` module is included in Python since v3.3 so this is not a separate requirement) * [Python](https://www.python.org/) 3.11+ (the `venv` module is included in Python since 3.3 so this is not a separate requirement)
* Git * [Git](https://git-scm.com/)
* Ansible-compatible secrets management (e.g. * [Ansible](https://docs.ansible.com/)-compatible secrets management (e.g.
[sops](https://getsops.io/) or [sops](https://getsops.io/) or
[Bitwarden Secrets Manager](https://bitwarden.com/products/secrets-manager/)) [Bitwarden Secrets Manager](https://bitwarden.com/products/secrets-manager/))

BIN
static/img/host-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
static/img/user-add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB