What you’ll accomplish: Understand the full deployment architecture, size your VM correctly, and confirm all prerequisites are in place before touching a terminal.
The Big Picture
Here’s what we’re building. Every component runs on a single Rocky Linux 9 host, with SSH connections outbound to your managed nodes:
+--------------------+
| Your Browser |
+--------+-----------+
|
HTTPS (443)
|
+--------+-----------+
| Apache httpd |
| (reverse proxy, |
| SSL termination)|
+--------+-----------+
|
HTTP (4440, loopback only)
|
+--------+-----------+
| Rundeck Server |
| (Java / Jetty) |
| |
| - Web UI |
| - REST API |
| - Job engine |
| - Log storage |
+----+----------+----+
| |
+------------+ +-------------+
| |
+---------+----------+ +-----------+---------+
| MariaDB | | Ansible |
| (job metadata, | | (playbook |
| execution | | execution via |
| history, | | plugin) |
| project config) | +-----------+---------+
+--------------------+ |
SSH (port 22)
|
+------------+------------+
| Managed Nodes |
| (Rocky, Pi, etc.) |
+-------------------------+
The key design decisions here:
- Apache sits in front of Rundeck. Users hit port 443 (HTTPS). Apache terminates SSL and proxies to Rundeck on localhost:4440. Rundeck never handles SSL directly — that means no Java keystore headaches, and certificate management works the way you’re used to.
- MariaDB runs locally. Port 3306 is bound to loopback. Rundeck connects over localhost. No network exposure for the database.
- Ansible runs on the Rundeck host. When Rundeck executes a playbook job, it invokes
ansible-playbooklocally. Ansible then reaches out to managed nodes over SSH.
Component Overview
| Component | What It Does | Where It Lives |
|---|---|---|
| Rundeck Server | Java application (embedded Jetty) that provides the web UI, REST API, job scheduling engine, and execution logging | /var/lib/rundeck/ (runtime), /etc/rundeck/ (config) |
| MariaDB | Stores job definitions, execution history, project configuration, and encrypted key storage. Replaces the default H2 embedded database | /var/lib/mysql/ (data), /etc/my.cnf.d/ (config) |
| Apache httpd | Reverse proxy with mod_ssl. Terminates HTTPS on port 443, forwards requests to Rundeck on port 4440 | /etc/httpd/ (config), /etc/pki/tls/ (certs) |
| Ansible | Playbook execution engine. Rundeck’s Ansible plugin calls ansible-playbook to run jobs against managed nodes | /usr/bin/ansible-playbook, inventory on Rundeck host |
| Java 11 (OpenJDK) | Runtime for Rundeck. Installed from Rocky’s base repos | /usr/lib/jvm/ |
Hardware Sizing
Here’s what actually works for a home lab, not what the official docs say you need:
| Resource | Minimum | Recommended | Notes |
|---|---|---|---|
| CPU | 2 cores | 4 cores | Java is CPU-hungry during job scheduling. 2 cores work for light use (<5 concurrent jobs). |
| RAM | 4 GB total | 8 GB total | The official docs say 8 GB minimum. In practice, a home lab with fewer than 10 nodes and fewer than 5 concurrent jobs runs fine on 4 GB with a 2 GB JVM heap. If you run other services on the same host, go with 8 GB. |
| Disk | 20 GB | 40 GB | Execution logs accumulate over time. 20 GB is plenty to start; monitor /var/lib/rundeck/logs/ and configure log retention later. |
| Swap | 2 GB | 2 GB | Java garbage collection pauses are less painful with swap available. Don’t skip this. |
Pro tip: If you’re running this on Proxmox, a VM with 4 cores, 4 GB RAM, and 32 GB disk is the sweet spot. You can always increase later — Proxmox makes that easy.
Network Requirements
Only one port needs to be exposed to your network. Everything else stays on loopback.
| Port | Protocol | Direction | Service | Exposure |
|---|---|---|---|---|
| 443 | TCP | Inbound | Apache httpd (HTTPS) | Network — this is the only port users access |
| 4440 | TCP | Loopback only | Rundeck HTTP | Apache proxies to this. Never expose it directly. |
| 4443 | TCP | Loopback only | Rundeck HTTPS (direct) | Only used if Rundeck handles SSL itself. We don’t — we use Apache. |
| 3306 | TCP | Loopback only | MariaDB | Database. Bind to 127.0.0.1. |
| 22 | TCP | Outbound | SSH to managed nodes | Rundeck dispatches commands and playbooks to nodes over SSH |
Firewall strategy: Open port 443 inbound. That’s it. Ports 4440 and 3306 stay on loopback and don’t need firewall rules. Outbound SSH to your managed node subnet should already be allowed by default.
Software Prerequisites
On the Rundeck host (the Rocky Linux 9 VM you’re building):
| Requirement | Version | How to Get It |
|---|---|---|
| Rocky Linux | 9.x (minimal install) | Fresh VM or bare metal |
| SELinux | Enforcing (default) | Don’t disable it. We’ll configure the booleans it needs. |
| Internet access | — | Required for package downloads during setup |
| Java | 11 (OpenJDK JRE) | Installed in Chapter 4 via dnf |
| MariaDB | 10.5+ | Installed in Chapter 3 via dnf (Rocky Linux base repos) |
| Ansible | ansible-core from AppStream | Installed in Chapter 5 via dnf |
On your workstation (where you run the deployment playbooks):
| Requirement | Version | Notes |
|---|---|---|
| Ansible | 2.14+ (ansible-core) | For running the deployment playbooks against the Rundeck host |
| SSH access | — | To the Rundeck host, with a sudo-capable user |
Pre-Flight Checklist
Run these on your Rundeck host before starting Chapter 3. Every check should pass.
Confirm the OS:
cat /etc/os-release | grep PRETTY_NAME
Expected output:
PRETTY_NAME="Rocky Linux 9.x (Blue Onyx)"
Confirm SELinux is enforcing:
getenforce
Expected output:
Enforcing
If this says Permissive or Disabled, fix it before proceeding. Edit /etc/selinux/config, set SELINUX=enforcing, and reboot. Running with SELinux disabled means every tutorial works — until you re-enable it in six months and everything breaks at once.
Confirm available RAM:
free -h
You need at least 4 GB total. If you’re under that, resize the VM before continuing.
Confirm available disk:
df -h /
You need at least 20 GB free on the root filesystem (or wherever /var/lib/ lives).
Confirm internet access:
curl -sL -o /dev/null -w "%{http_code}" https://packages.rundeck.com
Expected output:
200
The -L flag follows redirects. If you get a timeout or connection refused, fix your DNS or firewall rules first. The installation in later chapters pulls packages from the internet.
What to Have Ready
Before you start Chapter 3, gather these:
- The IP address or hostname of your Rundeck host. We’ll use
192.168.1.50as the example throughout this guide. - A DNS record (optional but recommended). Point
rundeck.example.comat your Rundeck host’s IP. If you don’t have internal DNS, the IP address works — you’ll just usehttps://192.168.1.50instead of a hostname. - An SSL certificate and key for the Rundeck hostname. Self-signed is fine for a home lab. If you don’t have one yet, we’ll cover generating a self-signed cert in Chapter 4.
- A list of managed nodes you want Rundeck to control — their IPs or hostnames, and a user account with SSH access.
- A strong password for the MariaDB
rundeckuser. Generate one now and store it in your Ansible vault. You’ll need it in the next chapter.
Everything in place? Let’s set up MariaDB.