Migrate Prometheus stack to Podman

This commit is contained in:
Fabio Scotto di Santolo
2026-09-08 22:59:56 +02:00
parent 7203ac6e2d
commit ab8c51a57d
13 changed files with 91 additions and 98 deletions

View File

@@ -52,7 +52,7 @@ Ansible-driven personal infrastructure repo for Fedora and Void desktops, Fedora
- Emacs is disabled by default; temporary Emacs check: `ansible-playbook ansible/site.yml --limit <host> --tags emacs --check --diff -e emacs_enabled=true` - Emacs is disabled by default; temporary Emacs check: `ansible-playbook ansible/site.yml --limit <host> --tags emacs --check --diff -e emacs_enabled=true`
- AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff` - AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff`
- Mail bootstrap: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh` - Mail bootstrap: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh`
- Server compose render: `docker compose -f /opt/docker/server/docker-compose.yml config` - Server compose render: `podman-compose -f /opt/docker/server/docker-compose.yml config` and `systemctl status podman-compose-server`
- DuckDNS config only: `ansible-playbook ansible/site.yml --limit prometheus --tags duckdns --check --diff` - DuckDNS config only: `ansible-playbook ansible/site.yml --limit prometheus --tags duckdns --check --diff`
## Conventions ## Conventions
@@ -103,12 +103,17 @@ The dotfile vars follow the same split: `desktop_common_dotfiles` carries mode-i
and disables diffs. Provisioning does not execute the updater or change its external schedule. and disables diffs. Provisioning does not execute the updater or change its external schedule.
- `rocky_server` is a child of both `platform_rocky` and `server`; `prometheus` is its active target. - `rocky_server` is a child of both `platform_rocky` and `server`; `prometheus` is its active target.
- The target must already provide `server_username` with local sudo access before the profile runs. - The target must already provide `server_username` with local sudo access before the profile runs.
- The Rocky profile installs Docker CE, uses firewalld, preserves SELinux enforcement, and renders the - The Rocky profile installs Podman and podman-compose, uses firewalld, preserves SELinux enforcement, and renders the
same server Compose stack. It does not transfer data, start containers, update DNS, or cut over traffic. same server Compose stack with a `podman-compose-server` systemd unit. It does not start, enable, transfer data,
update DNS, or cut over traffic; activating the stack is a manual step.
- Firewalld enables SSH, Cockpit (`9090/tcp`), HTTP and HTTPS. Nginx Proxy Manager publishes `80/tcp` and
`443/tcp`; bind its administration interface only to `127.0.0.1:81` and use `npm-tunnel` from Ikaros or Nymph.
Nextcloud remains disabled; do not provision `/srv/nextcloud` directories.
- `scripts/migrate_prometheus_data.sh` is the separate, source-host-run migration path. It dry-runs by - `scripts/migrate_prometheus_data.sh` is the separate, source-host-run migration path. It dry-runs by
default and requires explicit source-stack quiescing before copying persistent Docker data with rsync. default and requires explicit source-stack quiescing before copying persistent Docker data with rsync.
- Atlas-only OpenZFS, NFS, Samba, Cockpit, and Syncthing stay selected through Atlas host variables - Atlas-only OpenZFS, NFS, Samba, and Syncthing stay selected through Atlas host variables and must not
and must not leak into `rocky_server`. leak into `rocky_server`. Cockpit plus its Navigator and Podman extensions are selected explicitly for
Prometheus through its host variables.
## Atlas NAS Notes ## Atlas NAS Notes
- `atlas` is a remote Rocky Linux 9 NAS. Keep its connection, LAN, pool and mountpoint values in - `atlas` is a remote Rocky Linux 9 NAS. Keep its connection, LAN, pool and mountpoint values in

View File

@@ -178,12 +178,16 @@ Profilo orientato a servizi server e gestione di dotfiles dedicati.
Lo stato attuale del profilo server include: Lo stato attuale del profilo server include:
- installazione pacchetti Rocky via DNF, EPEL e CRB - installazione pacchetti Rocky via DNF, EPEL e CRB
- installazione e configurazione di Docker dal repository ufficiale - installazione di Podman e podman-compose
- abilitazione dei servizi systemd dichiarati in inventory/group vars - abilitazione dei servizi systemd dichiarati in inventory/group vars
- copia dei dotfiles server e rendering dei template server, incluso il `docker-compose.yml` dello stack servizi - copia dei dotfiles server e rendering dei template server, incluso il `docker-compose.yml` dello stack servizi e dell'unit `podman-compose-server` (attivazione manuale)
- attivazione di firewalld con servizio SSH esplicitamente abilitato - attivazione di firewalld con SSH, Cockpit (`9090/tcp`), HTTP e HTTPS abilitati
- Syncthing escluso dal profilo server Rocky - Syncthing escluso dal profilo server Rocky
Nginx Proxy Manager pubblica solo `80/tcp` e `443/tcp`; la sua interfaccia di amministrazione e
associata a `127.0.0.1:81` ed e raggiungibile da Ikaros o Nymph con l'alias Bash `npm-tunnel`.
Nextcloud resta disabilitato e il profilo non crea directory `/srv/nextcloud`.
### DuckDNS ### DuckDNS
`profile_server` genera `~/duckdns/duck.sh` con permessi `0700`, mantenendo il percorso dello `profile_server` genera `~/duckdns/duck.sh` con permessi `0700`, mantenendo il percorso dello
@@ -450,7 +454,7 @@ ansible-playbook ansible/site.yml --limit <host> --tags <tag1>,<tag2> --check --
ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff
ansible-lint ansible/roles/<role> ansible-lint ansible/roles/<role>
yamllint ansible/path/to/file.yml yamllint ansible/path/to/file.yml
docker compose -f /opt/docker/server/docker-compose.yml config podman-compose -f /opt/docker/server/docker-compose.yml config
``` ```
## Tag supportati dal playbook ## Tag supportati dal playbook

View File

@@ -104,11 +104,16 @@ That gives it Fedora packages through DNF, Docker from the official repository,
dotfiles and templates. The profile provisions configuration only: it does not transfer data, start dotfiles and templates. The profile provisions configuration only: it does not transfer data, start
the Compose stack, update DNS, or perform a cutover. the Compose stack, update DNS, or perform a cutover.
The server profile installs platform-specific packages, Docker CE from the official repository, The server profile installs platform-specific packages, Podman and podman-compose,
declared systemd services, the server Compose stack, and firewalld. The Rocky server excludes declared systemd services, the server Compose stack behind the `podman-compose-server` systemd unit, and firewalld. The Rocky server excludes
Syncthing. Rocky bind mounts use private SELinux relabeling for application data while host system Syncthing. Rocky bind mounts use private SELinux relabeling for application data while host system
files remain unchanged. files remain unchanged.
Firewalld enables SSH, Cockpit (`9090/tcp`), HTTP and HTTPS. Nginx Proxy Manager publishes only
`80/tcp` and `443/tcp`; its administration interface is bound to `127.0.0.1:81` and can be reached
from Ikaros or Nymph with the `npm-tunnel` Bash alias. Nextcloud remains disabled and the profile
does not provision any `/srv/nextcloud` directories.
Server identity comes from `server_username`, `server_user_group`, and `server_user_home` in `ansible/inventory/group_vars/server.yml`. `server_username` defaults to `username`, but it can be overridden, for example: Server identity comes from `server_username`, `server_user_group`, and `server_user_home` in `ansible/inventory/group_vars/server.yml`. `server_username` defaults to `username`, but it can be overridden, for example:
```bash ```bash
@@ -378,7 +383,7 @@ ansible-playbook ansible/site.yml --limit <host> --tags <tag1>,<tag2> --check --
ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff ansible-playbook ansible/site.yml --limit <host> --start-at-task "<task name>" --check --diff
ansible-lint ansible/roles/<role> ansible-lint ansible/roles/<role>
yamllint ansible/path/to/file.yml yamllint ansible/path/to/file.yml
docker compose -f /opt/docker/server/docker-compose.yml config podman-compose -f /opt/docker/server/docker-compose.yml config
``` ```
## Tags ## Tags

View File

@@ -18,11 +18,9 @@ rocky_syncthing_archive_url: >-
rocky_manage_openzfs_repo: false rocky_manage_openzfs_repo: false
rocky_manage_syncthing_binary: false rocky_manage_syncthing_binary: false
rocky_manage_docker_repo: false rocky_manage_podman: false
rocky_manage_github_cli_repo: false rocky_manage_github_cli_repo: false
rocky_docker_repo_url: https://download.docker.com/linux/rhel/docker-ce.repo
rocky_docker_repo_file: /etc/yum.repos.d/docker-ce.repo
rocky_github_cli_repo_url: https://cli.github.com/packages/rpm/gh-cli.repo rocky_github_cli_repo_url: https://cli.github.com/packages/rpm/gh-cli.repo
rocky_github_cli_repo_file: /etc/yum.repos.d/gh-cli.repo rocky_github_cli_repo_file: /etc/yum.repos.d/gh-cli.repo
@@ -47,8 +45,8 @@ rocky_packages_base:
- firewalld - firewalld
- openssh-server - openssh-server
- rsync - rsync
- selinux-policy-targeted
- sudo - sudo
rocky_profile_packages: [] rocky_profile_packages: []
rocky_docker_packages: [] rocky_podman_packages: []
rocky_docker_conflicting_packages: []

View File

@@ -1,5 +1,5 @@
--- ---
rocky_manage_docker_repo: true rocky_manage_podman: true
rocky_manage_github_cli_repo: true rocky_manage_github_cli_repo: true
rocky_profile_packages: rocky_profile_packages:
@@ -22,37 +22,22 @@ rocky_profile_packages:
- ranger - ranger
- ripgrep - ripgrep
rocky_docker_packages: rocky_podman_packages:
- containerd.io - podman
- docker-buildx-plugin - podman-compose
- docker-ce
- docker-ce-cli
- docker-compose-plugin
rocky_docker_conflicting_packages:
- docker
- docker-client
- docker-client-latest
- docker-common
- docker-engine
- docker-latest
- docker-latest-logrotate
- docker-logrotate
- runc
enabled_services: enabled_services:
- firewalld - firewalld
- docker - podman.socket
server_firewall_backend: firewalld server_firewall_backend: firewalld
server_firewalld_zone: public server_firewalld_zone: public
server_firewalld_services: server_firewalld_services:
- ssh - ssh
- cockpit
- http
- https
server_firewalld_ports: [] server_firewalld_ports: []
server_firewalld_absent_ports:
- 22000/tcp
- 22000/udp
- 21027/udp
server_sshd_service_name: sshd server_sshd_service_name: sshd
server_compose_selinux_mount_option: Z server_compose_selinux_mount_option: Z
server_syncthing_enabled: false server_syncthing_enabled: false

View File

@@ -86,14 +86,6 @@ server_directories:
owner: root owner: root
group: root group: root
mode: "0755" mode: "0755"
- path: /srv/nextcloud
owner: root
group: root
mode: "0755"
- path: /srv/nextcloud/data
owner: root
group: root
mode: "0755"
server_syncthing_enabled: true server_syncthing_enabled: true
server_syncthing_directories: server_syncthing_directories:

View File

@@ -50,16 +50,6 @@
state: enabled state: enabled
when: rocky_manage_openzfs_repo | bool when: rocky_manage_openzfs_repo | bool
- name: Configure official Docker RPM repository
tags: [packages, docker]
ansible.builtin.get_url:
url: "{{ rocky_docker_repo_url }}"
dest: "{{ rocky_docker_repo_file }}"
owner: root
group: root
mode: "0644"
when: rocky_manage_docker_repo | bool
- name: Configure official GitHub CLI RPM repository - name: Configure official GitHub CLI RPM repository
tags: [packages] tags: [packages]
ansible.builtin.get_url: ansible.builtin.get_url:
@@ -70,15 +60,6 @@
mode: "0644" mode: "0644"
when: rocky_manage_github_cli_repo | bool when: rocky_manage_github_cli_repo | bool
- name: Remove packages conflicting with Docker CE
tags: [packages, docker]
ansible.builtin.dnf:
name: "{{ rocky_docker_conflicting_packages }}"
state: absent
when:
- rocky_manage_docker_repo | bool
- rocky_docker_conflicting_packages | length > 0
- name: Refresh Rocky package metadata - name: Refresh Rocky package metadata
tags: [packages] tags: [packages]
ansible.builtin.dnf: ansible.builtin.dnf:
@@ -93,19 +74,21 @@
(rocky_common_packages | default([])) (rocky_common_packages | default([]))
+ (rocky_packages_base | default([])) + (rocky_packages_base | default([]))
+ (rocky_profile_packages | default([])) + (rocky_profile_packages | default([]))
+ (rocky_docker_packages | default([])) + (rocky_podman_packages | default([]))
+ (host_packages | default([])) + (host_packages | default([]))
) | unique ) | unique
}} }}
state: present state: present
- name: Add Rocky user to docker group - name: Ensure Podman runtime socket directory exists
tags: [packages, docker] tags: [packages, podman]
ansible.builtin.user: ansible.builtin.file:
name: "{{ effective_username }}" path: /run/podman
groups: docker state: directory
append: true owner: root
when: rocky_docker_packages | length > 0 group: root
mode: "0700"
when: rocky_manage_podman | bool
- name: Require supported architecture for Syncthing - name: Require supported architecture for Syncthing
tags: [packages, syncthing] tags: [packages, syncthing]

View File

@@ -4,3 +4,8 @@
ansible.builtin.service: ansible.builtin.service:
name: "{{ server_sshd_service_name }}" name: "{{ server_sshd_service_name }}"
state: reloaded state: reloaded
- name: Reload systemd for Podman Compose
tags: [services]
ansible.builtin.systemd:
daemon_reload: true

View File

@@ -67,6 +67,10 @@
label: "{{ item.dest }}" label: "{{ item.dest }}"
no_log: "{{ item.no_log | default(false) }}" no_log: "{{ item.no_log | default(false) }}"
- name: Manage Podman Compose stack
tags: [services, podman]
ansible.builtin.include_tasks: podman-compose.yml
- name: Disable SSH root login on server - name: Disable SSH root login on server
tags: [services] tags: [services]
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@@ -113,16 +117,3 @@
loop_control: loop_control:
label: "{{ item }}" label: "{{ item }}"
when: server_firewall_backend == 'firewalld' when: server_firewall_backend == 'firewalld'
- name: Remove disabled server ports from firewalld
tags: [services, packages]
ansible.posix.firewalld:
port: "{{ item }}"
zone: "{{ server_firewalld_zone }}"
state: disabled
permanent: true
immediate: true
loop: "{{ server_firewalld_absent_ports | default([]) }}"
loop_control:
label: "{{ item }}"
when: server_firewall_backend == 'firewalld'

View File

@@ -0,0 +1,10 @@
---
- name: Render Podman Compose systemd unit
tags: [services, podman]
ansible.builtin.template:
src: podman-compose-server.service.j2
dest: /etc/systemd/system/podman-compose-server.service
owner: root
group: root
mode: "0644"
notify: Reload systemd for Podman Compose

View File

@@ -0,0 +1,15 @@
[Unit]
Description=Podman Compose stack for {{ server_username }}
Requires=network-online.target
After=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory={{ server_container_stack_dir }}
ExecStart=/usr/bin/podman-compose up -d
ExecStop=/usr/bin/podman-compose down
ExecReload=/usr/bin/podman-compose up -d
[Install]
WantedBy=multi-user.target

View File

@@ -1,10 +1,10 @@
--- ---
{% set selinux_volume_option = server_compose_selinux_mount_option | default('') %} {% set selinux_volume_option = server_compose_selinux_mount_option | default('') %}
version: "3.8" name: server
services: services:
navidrome: navidrome:
image: deluan/navidrome:latest image: docker.io/deluan/navidrome:latest
container_name: navidrome container_name: navidrome
restart: unless-stopped restart: unless-stopped
expose: expose:
@@ -23,19 +23,18 @@ services:
depends_on: depends_on:
- navidromedb - navidromedb
nginx-proxy-manager: nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest image: docker.io/jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager container_name: nginx-proxy-manager
restart: unless-stopped restart: unless-stopped
ports: ports:
- "80:80" - "80:80"
- "443:443" - "443:443"
- "81:81" - "127.0.0.1:81:81"
volumes: volumes:
- "/opt/npm/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}" - "/opt/npm/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
- "/opt/npm/letsencrypt:/etc/letsencrypt{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}" - "/opt/npm/letsencrypt:/etc/letsencrypt{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}"
networks: networks:
- web - web
- gitea
# Disabled: prometheus does not have enough resources to run Nextcloud AIO. # Disabled: prometheus does not have enough resources to run Nextcloud AIO.
# nextcloud-aio-mastercontainer: # nextcloud-aio-mastercontainer:
@@ -57,7 +56,7 @@ services:
# - web # - web
navidromedb: navidromedb:
image: postgres:13 image: docker.io/library/postgres:13
container_name: navidromedb container_name: navidromedb
restart: unless-stopped restart: unless-stopped
mem_limit: 2048m mem_limit: 2048m
@@ -78,7 +77,7 @@ services:
- USER_GID=1100 - USER_GID=1100
restart: always restart: always
networks: networks:
- gitea - web
volumes: volumes:
- /opt/gitea/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }} - /opt/gitea/data:/data{{ ':' ~ selinux_volume_option if selinux_volume_option else '' }}
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
@@ -90,7 +89,7 @@ services:
{% if server_syncthing_enabled | default(true) | bool %} {% if server_syncthing_enabled | default(true) | bool %}
syncthing: syncthing:
image: syncthing/syncthing:2 image: docker.io/syncthing/syncthing:2
container_name: syncthing container_name: syncthing
hostname: syncthing hostname: syncthing
restart: unless-stopped restart: unless-stopped
@@ -111,8 +110,6 @@ networks:
web: web:
name: server_web name: server_web
external: false external: false
gitea:
external: false
# volumes: # volumes:
# nextcloud_aio_mastercontainer: # nextcloud_aio_mastercontainer:

View File

@@ -1,2 +1,5 @@
# Additional Bash aliases. # Additional Bash aliases.
# Keep this file as the extension point for shared aliases. # Keep this file as the extension point for shared aliases.
# Nginx Proxy Manager administration tunnel on Prometheus.
alias npm-tunnel='ssh -N -o ExitOnForwardFailure=yes -L 8181:127.0.0.1:81 rocky@179.237.102.172'