Skip to content

Commit 69c4660

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 69c4660

File tree

34 files changed

+1747
-899
lines changed

34 files changed

+1747
-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: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,19 @@ 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/` with group ownership and permissions automatically configured during deployment to allow the `foremanctl` user to read them
57+
5458
### Current Limitations
5559

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

100104
**Default Source (`src/vars/default_certificates.yml`):**
101105
```yaml
106+
certificates_ca_directory: /var/lib/foremanctl/certificates
102107
ca_certificate: "{{ certificates_ca_directory }}/certs/ca.crt"
103108
server_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}.crt"
104109
client_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}-client.crt"
105110
```
106111
107112
**Installer Source (`src/vars/installer_certificates.yml`):**
108113
```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"
114+
certificates_ca_directory: /root/ssl-build
115+
ca_certificate: "{{ certificates_ca_directory }}/katello-default-ca.crt"
116+
server_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-apache.crt"
117+
client_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-foreman-client.crt"
112118
```
113119

114120
#### Integration with Deployment
@@ -138,12 +144,14 @@ The `certificate_checks` role uses `foreman-certificate-check` binary to validat
138144

139145
**Directory Structure:**
140146
```
141-
/root/certificates/
147+
/var/lib/foremanctl/certificates/
142148
├── certs/ # Public certificates
143149
├── private/ # Private keys and passwords
144150
└── requests/ # Certificate signing requests
145151
```
146152
153+
All certificate files and directories are owned by `foremanctl:foremanctl` to support rootless Podman deployments.
154+
147155
**OpenSSL Configuration:**
148156
- Custom configuration template supports SAN extensions
149157
- 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)