Skip to content

Commit 53a4056

Browse files
pablomhclaude
andcommitted
Convert Podman Quadlet deployment from rootful to rootless
Enables Foreman deployment using rootless Podman containers, improving security by eliminating root privileges for container operations while maintaining full functionality of the Foreman/Katello stack. What this achieves: - Rootless deployment: All containers run without root privileges - Single service user: Entire stack (foreman, candlepin, postgresql, redis, pulp) runs under dedicated foremanctl user - Migration support: Automated playbook converts existing rootful deployments - Namespace isolation: Container volumes properly mapped to user namespaces - Port access: Unprivileged ports configured for HTTP/HTTPS access New capabilities: - Fresh deployments use rootless mode by default - Existing rootful deployments can migrate with automated playbook - All certificates, data, and configuration preserved during migration - User lingering enabled for service persistence across reboots This change modernizes the deployment model to follow container security best practices while maintaining backward compatibility through the migration playbook. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 60b55aa commit 53a4056

File tree

34 files changed

+1733
-899
lines changed

34 files changed

+1733
-899
lines changed

development/playbooks/deploy-dev/deploy-dev.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
---
2+
- name: Setup rootless user environment
3+
hosts: "{{ target_host if target_host is defined and target_host != '' else 'quadlet' }}"
4+
become: true
5+
roles:
6+
- role: ../../../src/roles/rootless_user
7+
tasks:
8+
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
9+
ansible.builtin.set_fact:
10+
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"
11+
212
- name: Deploy Foreman Development Environment
313
hosts: "{{ target_host if target_host is defined and target_host != '' else 'quadlet' }}"
414
become: true
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
---
2+
- name: Setup rootless user environment
3+
hosts:
4+
- database
5+
become: true
6+
roles:
7+
- role: ../../../src/roles/rootless_user
8+
tasks:
9+
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
10+
ansible.builtin.set_fact:
11+
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"
12+
213
- name: Setup remote database
314
hosts:
415
- database
516
become: true
617
vars_files:
718
- "../../../src/vars/database.yml"
19+
- "../../../src/vars/base.yaml"
820
roles:
921
- role: pre_install
1022
- role: postgresql

docs/certificates.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,23 @@ foremanctl deploy --certificate-source=installer
4242
After deployment, certificates are available at:
4343

4444
**Default Source:**
45-
- CA Certificate: `/root/certificates/certs/ca.crt`
46-
- Server Certificate: `/root/certificates/certs/<hostname>.crt`
47-
- Client Certificate: `/root/certificates/certs/<hostname>-client.crt`
45+
- CA Certificate: `/var/lib/foremanctl/certificates/certs/ca.crt`
46+
- Server Certificate: `/var/lib/foremanctl/certificates/certs/<hostname>.crt`
47+
- Client Certificate: `/var/lib/foremanctl/certificates/certs/<hostname>-client.crt`
4848

4949
**Installer Source:**
5050
- CA Certificate: `/root/ssl-build/katello-default-ca.crt`
5151
- Server Certificate: `/root/ssl-build/<hostname>/<hostname>-apache.crt`
5252
- Client Certificate: `/root/ssl-build/<hostname>/<hostname>-foreman-client.crt`
5353

54+
**Note for Rootless Deployments:**
55+
- Default certificates are owned by `foremanctl:foremanctl` user and group
56+
- Installer certificates remain in `/root/ssl-build/` but must be readable by foremanctl user:
57+
```bash
58+
chgrp -R foremanctl /root/ssl-build
59+
chmod -R g+rX /root/ssl-build
60+
```
61+
5462
### Current Limitations
5563

5664
- Only supports single hostname (no multiple DNS names)
@@ -99,16 +107,18 @@ Certificate paths are defined in source-specific variable files:
99107

100108
**Default Source (`src/vars/default_certificates.yml`):**
101109
```yaml
110+
certificates_ca_directory: /var/lib/foremanctl/certificates
102111
ca_certificate: "{{ certificates_ca_directory }}/certs/ca.crt"
103112
server_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}.crt"
104113
client_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}-client.crt"
105114
```
106115
107116
**Installer Source (`src/vars/installer_certificates.yml`):**
108117
```yaml
109-
ca_certificate: "/root/ssl-build/katello-default-ca.crt"
110-
server_certificate: "/root/ssl-build/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-apache.crt"
111-
client_certificate: "/root/ssl-build/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-foreman-client.crt"
118+
certificates_ca_directory: /root/ssl-build
119+
ca_certificate: "{{ certificates_ca_directory }}/katello-default-ca.crt"
120+
server_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-apache.crt"
121+
client_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-foreman-client.crt"
112122
```
113123

114124
#### Integration with Deployment
@@ -138,12 +148,14 @@ The `certificate_checks` role uses `foreman-certificate-check` binary to validat
138148

139149
**Directory Structure:**
140150
```
141-
/root/certificates/
151+
/var/lib/foremanctl/certificates/
142152
├── certs/ # Public certificates
143153
├── private/ # Private keys and passwords
144154
└── requests/ # Certificate signing requests
145155
```
146156
157+
All certificate files and directories are owned by `foremanctl:foremanctl` to support rootless Podman deployments.
158+
147159
**OpenSSL Configuration:**
148160
- Custom configuration template supports SAN extensions
149161
- Single DNS entry per certificate: `subjectAltName = DNS:{{ certificates_hostname }}`

src/playbooks/deploy/deploy.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
---
2-
- name: Setup quadlet demo machine
2+
- name: Setup rootless user environment
3+
hosts:
4+
- quadlet
5+
become: true
6+
roles:
7+
- role: rootless_user
8+
tasks:
9+
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
10+
ansible.builtin.set_fact:
11+
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"
12+
13+
- name: Deploy Foreman services
314
hosts:
415
- quadlet
516
become: true

0 commit comments

Comments
 (0)