Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
de4d5eb
Bump actions/upload-artifact from 6 to 7
dependabot[bot] Feb 27, 2026
ebf0390
Bump actions/download-artifact from 7 to 8
dependabot[bot] Feb 27, 2026
9d2991f
Drop unused reference to foreman_development_hammer_git_revision
adamruzicka Feb 26, 2026
140bcd3
Use different way of setting up CRB on RHEL in development
adamruzicka Feb 26, 2026
7159cff
Update defaults to define 4 generic timers
archanaserver Nov 27, 2025
eaab5b5
set boxes for each machine individually
evgeni Sep 19, 2025
1c2fc61
make it possible to override the base box from env
evgeni Sep 19, 2025
9eb10e4
run on el10 too
evgeni Sep 19, 2025
fd087ec
use hammer copr on el10
evgeni Sep 19, 2025
560f355
Force vagrant provision
evgeni Sep 23, 2025
10c679b
Configure smtp as email delivery method
Feb 26, 2026
9ccd22d
remove migration containers after execution
evgeni Mar 3, 2026
0529a72
Add rootless user infrastructure and base configuration
pablomh Feb 26, 2026
ecfe9b2
Update certificate generation for rootless deployment
pablomh Feb 26, 2026
d8763b8
Add rootless support for PostgreSQL service
pablomh Feb 26, 2026
fd7fd6b
Add rootless support for Redis service
pablomh Feb 26, 2026
d5ad490
Add rootless support for Candlepin service
pablomh Feb 26, 2026
cef6a8b
Add rootless support for Pulp services
pablomh Feb 26, 2026
d4d9d54
Add rootless support for Foreman service
pablomh Feb 26, 2026
307fb8f
Add rootless support for Foreman Proxy service
pablomh Feb 26, 2026
f3a23e1
Add rootless support for systemd target
pablomh Feb 26, 2026
265810d
Add migration playbook for rootful to rootless conversion
pablomh Feb 26, 2026
187c0cb
Update deployment playbooks for rootless support
pablomh Feb 26, 2026
2c987e5
Add fapolicyd rule for Python execution in /var/tmp
pablomh Feb 26, 2026
2c7d7ce
Update tests for rootless deployment
pablomh Feb 26, 2026
026990b
Update CI workflow for rootless deployment
pablomh Feb 26, 2026
76d6e9e
Add netavark, aardvark-dns, and passt for Podman private networks
pablomh Feb 26, 2026
e73f269
Add tests to verify Podman private network configuration prerequisites
pablomh Feb 26, 2026
5090263
Add podman_network role for creating private networks
pablomh Feb 26, 2026
8dc1c49
Add tests for podman_network role functionality
pablomh Feb 26, 2026
7848b77
Add iop_kafka
ehelms Dec 2, 2025
bf052bc
Add iop_ingress
ehelms Dec 2, 2025
1c0b24c
Add iop_puptoo
ehelms Dec 2, 2025
2120c50
Add iop_yuptoo
ehelms Dec 2, 2025
f911fbb
Add iop_engine
ehelms Dec 2, 2025
e2aae80
Add iop_gateway
ehelms Dec 3, 2025
cd74db3
Add iop_inventory
ehelms Dec 3, 2025
f2abdca
Add iop_advisor
ehelms Dec 4, 2025
19dc030
Add iop_remediation
ehelms Dec 4, 2025
dff4dc4
Add iop_vmaas and iop_vulnerability
ehelms Dec 4, 2025
8a68646
Add frontends for advisor and vulnerability
ehelms Dec 4, 2025
3312a88
Add iop test github actions
ehelms Dec 5, 2025
bac8ce7
Specify explicit volume mount permissions
ehelms Feb 13, 2026
91f768d
Run all IOP services as a rootless user
pablomh Feb 28, 2026
d8bf5de
Replace cd /tmp + sudo with runuser in tests
pablomh Mar 3, 2026
88624aa
Add IOP network isolation test
pablomh Mar 3, 2026
48ec5d2
Fix create user config directories on CentOS 10
pablomh Mar 3, 2026
ffe2873
Enable Ansible pipelining to fix become_user on CentOS 10
pablomh Mar 3, 2026
66cdaad
Install acl package to fix become_user on CentOS 10
pablomh Mar 3, 2026
c982144
Skip foreman-selinux install on EL10
pablomh Mar 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Build tarball
run: make dist
- name: Upload tarball to GitHub cache
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: release-tarball
path: 'foremanctl-*.tar.gz'
Expand All @@ -40,7 +40,7 @@ jobs:
contents: write # clone repo and create release
steps:
- name: Download tarball from GitHub cache
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: release-tarball
- name: Create Release Page
Expand Down
37 changes: 28 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,30 @@ jobs:
- none
database:
- internal
box:
- centos/stream9
- centos/stream10
iop:
- enabled
exclude:
- certificate_source: installer
box: centos/stream10
include:
- certificate_source: default
security: fapolicyd
database: internal
box: centos/stream9
- certificate_source: default
security: none
database: external
box: centos/stream9
runs-on: ubuntu-24.04
name: "Tests (certificates: ${{ matrix.certificate_source }}, database: ${{ matrix.database }}, security: ${{ matrix.security }})"
env:
FOREMANCTL_BASE_BOX: ${{ matrix.box }}
name: "Tests (certificates: ${{ matrix.certificate_source }}, database: ${{ matrix.database }}, security: ${{ matrix.security }}, box: ${{ matrix.box }}, iop: ${{ matrix.iop }})"
steps:
- name: generate artifact suffix
run: echo "ARTIFACT_SUFFIX=$(echo '${{ matrix.certificate_source }}-${{ matrix.security }}-${{ matrix.database }}-${{ matrix.box }}-${{ matrix.iop }}' | tr -cd '[:alnum:]-')" >> "${GITHUB_ENV}"
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
Expand Down Expand Up @@ -92,6 +106,7 @@ jobs:
run: |
vagrant ssh --command "echo 'allow perm=any pattern=ld_so exe=/usr/bin/crun : path=/usr/lib64/libsystemd.so.0' | sudo tee -a /etc/fapolicyd/rules.d/15-foremanctl.rules" quadlet
vagrant ssh --command "echo 'allow perm=any all : dir=/home/vagrant/.ansible/tmp/' | sudo tee -a /etc/fapolicyd/rules.d/15-foremanctl.rules" quadlet
vagrant ssh --command "echo 'allow perm=open exe=/usr/bin/python3.9 : dir=/var/tmp/ ftype=text/x-python' | sudo tee -a /etc/fapolicyd/rules.d/15-foremanctl.rules" quadlet
vagrant ssh quadlet -- sudo systemctl restart fapolicyd
- name: Run image pull
run: |
Expand All @@ -108,26 +123,30 @@ jobs:
- name: Add optional feature - foreman_azure_rm and foreman_google
run: |
./foremanctl deploy --add-feature foreman_azure_rm --add-feature foreman_google
- name: Enable iop
if: matrix.iop == 'enabled'
run: |
./foremanctl deploy --add-feature iop
- name: Run tests
run: |
./forge test --pytest-args="--certificate-source=${{ matrix.certificate_source }} --database-mode=${{ matrix.database }}"
./forge test --pytest-args="--certificate-source=${{ matrix.certificate_source }} --database-mode=${{ matrix.database }} --user=foremanctl"
- name: Run smoker
run: |
./forge smoker
- name: Archive smoker report
if: ${{ always() }}
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: smoker-${{ matrix.certificate_source }}-${{ matrix.security }}-${{ matrix.database }}
name: smoker-${{ env.ARTIFACT_SUFFIX }}
path: "/home/runner/smoker/report/"
- name: Generate sos reports
if: ${{ always() }}
run: ./forge sos
- name: Archive sos reports
if: ${{ always() }}
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: sosreport-${{ matrix.certificate_source }}-${{ matrix.security }}-${{ matrix.database }}
name: sosreport-${{ env.ARTIFACT_SUFFIX }}
path: sos/
- name: Setup upterm session
if: ${{ failure() }}
Expand Down Expand Up @@ -219,7 +238,7 @@ jobs:
./foremanctl deploy --add-feature foreman_azure_rm --add-feature foreman_google
- name: Stop services
run:
vagrant ssh quadlet -- sudo systemctl stop foreman.target
vagrant ssh quadlet -- sudo systemctl --machine=foremanctl@ --user stop foreman.target
- name: Configure upgrade version
run: |
sed -i '/container_tag_stream:/ s/:.*/: "${{ matrix.upgrade_to }}"/' src/vars/images.yml
Expand All @@ -231,13 +250,13 @@ jobs:
./foremanctl deploy
- name: Run tests
run: |
./forge test
./forge test --pytest-args="--user=foremanctl"
- name: Generate sos reports
if: ${{ always() }}
run: ./forge sos
- name: Archive sos reports
if: ${{ always() }}
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: sosreport-upgrade
path: sos/
Expand Down
4 changes: 3 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Vagrant.configure("2") do |config|
config.vm.box = "centos/stream9"
config.vm.synced_folder ".", "/vagrant"

config.vm.provision("etc_hosts", type: 'ansible') do |ansible|
Expand All @@ -12,6 +11,7 @@ Vagrant.configure("2") do |config|
end

config.vm.define "quadlet" do |override|
override.vm.box = ENV.fetch("FOREMANCTL_BASE_BOX", "centos/stream9")
override.vm.hostname = "quadlet.example.com"

override.vm.provider "libvirt" do |libvirt, provider|
Expand All @@ -22,6 +22,7 @@ Vagrant.configure("2") do |config|
end

config.vm.define "client" do |override|
override.vm.box = "centos/stream9"
override.vm.hostname = "client.example.com"

override.vm.provider "libvirt" do |libvirt, provider|
Expand All @@ -30,6 +31,7 @@ Vagrant.configure("2") do |config|
end

config.vm.define "database" do |override|
override.vm.box = "centos/stream9"
override.vm.hostname = "database.example.com"

override.vm.provider "libvirt" do |libvirt, provider|
Expand Down
10 changes: 10 additions & 0 deletions development/playbooks/deploy-dev/deploy-dev.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
---
- name: Setup rootless user environment
hosts: "{{ target_host if target_host is defined and target_host != '' else 'quadlet' }}"
become: true
roles:
- role: rootless_user
tasks:
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
ansible.builtin.set_fact:
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"

- name: Deploy Foreman Development Environment
hosts: "{{ target_host if target_host is defined and target_host != '' else 'quadlet' }}"
become: true
Expand Down
12 changes: 12 additions & 0 deletions development/playbooks/remote-database/remote-database.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
---
- name: Setup rootless user environment
hosts:
- database
become: true
roles:
- role: rootless_user
tasks:
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
ansible.builtin.set_fact:
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"

- name: Setup remote database
hosts:
- database
become: true
vars_files:
- "../../../src/vars/database.yml"
- "../../../src/vars/base.yaml"
roles:
- role: pre_install
- role: postgresql
13 changes: 13 additions & 0 deletions development/playbooks/setup-repositories/setup-repositories.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,23 @@
name: theforeman.operations.puppet_repositories
vars:
foreman_puppet_repositories_version: "8"
when:
- ansible_distribution_major_version == '9'

- name: Setup Foreman repositories
ansible.builtin.include_role:
name: theforeman.operations.foreman_repositories
vars:
foreman_repositories_version: nightly
foreman_repositories_katello_version: nightly
when:
- ansible_distribution_major_version == '9'

- name: Enable hammer-el10 copr
community.general.copr:
host: copr.fedorainfracloud.org
state: enabled
name: evgeni/hammer-el10
chroot: rhel-10-x86_64
when:
- ansible_distribution_major_version == '10'
7 changes: 7 additions & 0 deletions development/playbooks/vms/vms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
chdir: "{{ inventory_dir }}/../"
changed_when: false

- name: Force vagrant provision
ansible.builtin.command:
cmd: "vagrant provision {{ vms | default() }}"
args:
chdir: "{{ inventory_dir }}/../"
changed_when: false

- name: Create local_vagrant inventory
ansible.builtin.command:
cmd: ../../scripts/vagrant.py --yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
git_repository_user: "{{ foreman_development_user }}"
git_repository_repository_owner: "theforeman"
git_repository_repository_name: "hammer-cli"
git_repository_revision: "{{ foreman_development_hammer_git_revision }}"
git_repository_secondary_remote_owner: "{{ foreman_development_github_username }}"

- name: Setup hammer-cli-foreman
Expand Down
11 changes: 11 additions & 0 deletions development/roles/foreman_development/tasks/smart-proxy/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@
community.general.dnf_config_manager:
name: crb
state: enabled
when:
- ansible_facts['distribution'] != "RedHat"

- name: Ensure the crb repository is enabled
ansible.builtin.command:
cmd: >-
subscription-manager repos
--enable codeready-builder-for-rhel-{{ ansible_facts['distribution_major_version'] }}-{{ ansible_facts['architecture'] }}-rpms
changed_when: true
when:
- ansible_facts['distribution'] == "RedHat"

- name: Install smart-proxy dependencies
ansible.builtin.package:
Expand Down
2 changes: 1 addition & 1 deletion development/roles/foreman_installer_certs/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

# utilize https://github.com/theforeman/foreman-installer/pull/935
- name: Generate certs
ansible.builtin.command: foreman-certs --apache true --foreman true --candlepin true
ansible.builtin.command: foreman-certs --apache true --foreman true --candlepin true --iop true
changed_when: false
22 changes: 15 additions & 7 deletions docs/certificates.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,19 @@ foremanctl deploy --certificate-source=installer
After deployment, certificates are available at:

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

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

**Note for Rootless Deployments:**
- Default certificates are owned by `foremanctl:foremanctl` user and group
- Installer certificates remain in `/root/ssl-build/` with group ownership and permissions automatically configured during deployment to allow the `foremanctl` user to read them

### Current Limitations

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

**Default Source (`src/vars/default_certificates.yml`):**
```yaml
certificates_ca_directory: /var/lib/foremanctl/certificates
ca_certificate: "{{ certificates_ca_directory }}/certs/ca.crt"
server_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}.crt"
client_certificate: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}-client.crt"
```

**Installer Source (`src/vars/installer_certificates.yml`):**
```yaml
ca_certificate: "/root/ssl-build/katello-default-ca.crt"
server_certificate: "/root/ssl-build/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-apache.crt"
client_certificate: "/root/ssl-build/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-foreman-client.crt"
certificates_ca_directory: /root/ssl-build
ca_certificate: "{{ certificates_ca_directory }}/katello-default-ca.crt"
server_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-apache.crt"
client_certificate: "{{ certificates_ca_directory }}/{{ ansible_facts['fqdn'] }}/{{ ansible_facts['fqdn'] }}-foreman-client.crt"
```

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

**Directory Structure:**
```
/root/certificates/
/var/lib/foremanctl/certificates/
├── certs/ # Public certificates
├── private/ # Private keys and passwords
└── requests/ # Certificate signing requests
```

All certificate files and directories are owned by `foremanctl:foremanctl` to support rootless Podman deployments.

**OpenSSL Configuration:**
- Custom configuration template supports SAN extensions
- Single DNS entry per certificate: `subjectAltName = DNS:{{ certificates_hostname }}`
Expand Down
32 changes: 31 additions & 1 deletion src/playbooks/deploy/deploy.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
---
- name: Setup quadlet demo machine
- name: Setup rootless user environment
hosts:
- quadlet
become: true
roles:
- role: rootless_user
tasks:
- name: Map rootless_user_xdg_runtime_dir to foremanctl namespace
ansible.builtin.set_fact:
foremanctl_xdg_runtime_dir: "{{ rootless_user_xdg_runtime_dir }}"

- name: Deploy Foreman services
hosts:
- quadlet
become: true
Expand All @@ -12,6 +23,21 @@
- "../../vars/database.yml"
- "../../vars/foreman.yml"
- "../../vars/base.yaml"
pre_tasks:
- name: Add iop databases
when:
- "'iop' in enabled_features"
- database_mode == 'internal'
block:
- name: Include iop databases
ansible.builtin.include_vars:
file: "../../vars/database_iop.yml"

- name: Combine lists
ansible.builtin.set_fact:
postgresql_databases: "{{ postgresql_databases + iop_postgresql_databases }}"
postgresql_users: "{{ postgresql_users + iop_postgresql_users }}"

roles:
- role: pre_install
- role: checks
Expand All @@ -31,6 +57,10 @@
- pulp
- foreman
- role: systemd_target
- role: iop_core
when:
- "'iop' in enabled_features"
- database_mode == 'internal'
- role: foreman_proxy
when:
- "'foreman-proxy' in enabled_features"
Expand Down
15 changes: 15 additions & 0 deletions src/playbooks/migrate-to-rootless/metadata.obsah.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
help: |
Migrate existing rootful Foreman deployment to rootless

WARNING: This is a destructive operation that will:
- Stop all running services
- Transfer ownership of data volumes
- Remove system-scoped systemd units
- Recreate everything in user scope

PREREQUISITES:
- Backup all data before running this migration
- Ensure no active users or operations are running
- Test this in a non-production environment first
...
Loading
Loading