System Prep
Before installing any service, update the package repositories and install the developer tools the mo-installer and moctl depend on.
1.1 Update the system
sudo dnf update -y
sudo reboot
1.2 Enable the EPEL repository
EPEL provides utilities that the installer expects (jq, bash-completion, and others) but RHEL doesn’t ship by default.
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf update -y
Note. If
subscription-manageris not registered, also enable the CodeReady Linux Builder repo:sudo subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms.
1.3 Install required utilities
sudo dnf install -y unzip wget curl jq net-tools vim bash-completion tar lsof telnet firewalld
1.4 Configure the firewall
Open the ports the IDP needs. The DB port (5432 for Postgres, 3306 for MySQL, 1433 for MSSQL, 1521 for Oracle) is opened in the database section.
sudo systemctl enable --now firewalld
# IDP service ports
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=8070/tcp
sudo firewall-cmd --permanent --add-port=8071/tcp
sudo firewall-cmd --permanent --add-port=8072/tcp
# Redis (bundled with installer) and RabbitMQ
sudo firewall-cmd --permanent --add-port=6379/tcp
sudo firewall-cmd --permanent --add-port=5672/tcp
sudo firewall-cmd --permanent --add-port=15672/tcp
sudo firewall-cmd --reload
1.5 Set SELinux to permissive
The IDP microservices communicate locally on a wide port range; SELinux enforcing blocks parts of that. Persist the change so it survives reboots.
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
getenforce
Expected output: Permissive.
Note. RHEL 9 ships nftables under the hood for
firewalld. The commands above are unchanged from RHEL 8, but if you’ve replaced firewalld with raw nftables, manage the equivalent rules yourself.
Database
PostgreSQL 16 is the default backend for miniOrange IDP 5.0.0. The installer ships the PostgreSQL JDBC driver, so no manual driver placement is needed.
2.1 Add the PGDG repository
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
2.2 Disable the built-in PostgreSQL module
RHEL 9 ships an older PostgreSQL via its AppStream module; disabling it avoids a version conflict with PGDG.
sudo dnf -qy module disable postgresql
2.3 Install PostgreSQL 16
sudo dnf install -y postgresql16-server postgresql16 postgresql16-contrib
2.4 Initialise and start the service
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable --now postgresql-16
sudo systemctl status postgresql-16
2.5 Create the miniOrange database and user
sudo -u postgres psql <<'SQL'
CREATE USER moadmin WITH PASSWORD 'Password123';
CREATE DATABASE miniorangedb OWNER moadmin;
ALTER USER moadmin WITH SUPERUSER;
SQL
Why SUPERUSER. The IDP initialisation wizard runs schema creation and migrations on first startup. SUPERUSER avoids permission errors during this step. You can downgrade the role to a constrained owner after initialisation if your policy requires it.
2.6 Switch authentication to md5
PostgreSQL on RHEL defaults to ident for local TCP connections; the IDP authenticates with username and password over TCP, so switch to md5.
sudo sed -i \
-E 's/^(host\s+all\s+all\s+(127\.0\.0\.1\/32|::1\/128)\s+)ident/\1md5/' \
/var/lib/pgsql/16/data/pg_hba.conf
sudo systemctl restart postgresql-16
If you want the IDP to connect from a different host, also append a row like host all moadmin 10.0.0.0/8 md5 and reload.
2.7 Open the PostgreSQL port (only if remote access is needed)
sudo firewall-cmd --permanent --add-port=5432/tcp
sudo firewall-cmd --reload
2.8 Verify
PGPASSWORD=Password123 psql -h 127.0.0.1 -U moadmin -d miniorangedb -c '\l'
miniorangedb should appear in the output.
Values for the /initialize wizard
Keep these handy; you’ll enter them in Section 5 after the installer finishes.
| Field | Value |
|---|---|
| Database Type | PostgreSQL |
| Host | 127.0.0.1 |
| Port | 5432 |
| Database name | miniorangedb |
| Username | moadmin |
| Password | Password123 |
MySQL 8.4 LTS as the IDP backend. These steps are derived from the MySQL community repo install path combined with the JDBC driver placement convention from the Oracle source flow; review before production use.
2.1 Disable the built-in MySQL module
sudo dnf -qy module disable mysql
2.2 Add the MySQL community repository
sudo dnf install -y https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
sudo dnf clean all && sudo dnf makecache
2.3 Install MySQL 8.4
sudo dnf install -y mysql-community-server mysql-community-client
sudo systemctl enable --now mysqld
2.4 Retrieve the temporary root password
MySQL 8.x generates a one-time root password on first start.
sudo grep 'temporary password' /var/log/mysqld.log
2.5 Secure the installation
sudo mysql_secure_installation
Set a permanent root password when prompted. Answer yes to removing anonymous users, disallowing remote root login, removing the test database, and reloading privileges.
2.6 Create the miniOrange database and user
mysql -u root -p <<'SQL'
CREATE DATABASE miniorangedb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moadmin'@'localhost' IDENTIFIED BY 'Password123';
CREATE USER 'moadmin'@'%' IDENTIFIED BY 'Password123';
GRANT ALL PRIVILEGES ON miniorangedb.* TO 'moadmin'@'localhost';
GRANT ALL PRIVILEGES ON miniorangedb.* TO 'moadmin'@'%';
FLUSH PRIVILEGES;
SQL
Note. MySQL 8.4 defaults the authentication plugin to
caching_sha2_password. Themysql-connector-j8.x driver supports this; older drivers do not.
2.7 Place the MySQL JDBC driver (derived assumption)
The miniOrange v5.0.0 source documentation requires manual driver placement only for Oracle. By analogy with that flow, MySQL on a non-Postgres deployment likely needs mysql-connector-j placed in the same directory. Confirm with miniOrange support before relying on this step.
sudo mkdir -p /opt/miniorange/drivers
cd /tmp
sudo wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-8.4.0-1.el9.noarch.rpm
sudo dnf install -y ./mysql-connector-j-8.4.0-1.el9.noarch.rpm
sudo cp /usr/share/java/mysql-connector-j-8.4.0.jar /opt/miniorange/drivers/
sudo chmod 644 /opt/miniorange/drivers/mysql-connector-j-8.4.0.jar
2.8 Open the MySQL port (only if remote access is needed)
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload
2.9 Verify
mysql -u moadmin -pPassword123 -h 127.0.0.1 -e 'SHOW DATABASES;'
miniorangedb should appear in the output.
Values for the /initialize wizard
| Field | Value |
|---|---|
| Database Type | MySQL |
| Host | 127.0.0.1 |
| Port | 3306 |
| Database name | miniorangedb |
| Username | moadmin |
| Password | Password123 |
Microsoft SQL Server 2022 on RHEL 9. Microsoft officially supports MSSQL on RHEL 9. The IDP wiring is derived from the Oracle source flow (driver placement) plus the standard mssql-server install.
2.1 Verify system requirements
MSSQL on Linux requires at least 2 GB of RAM. Verify before installing.
free -h
2.2 Add the Microsoft repository
sudo curl -o /etc/yum.repos.d/mssql-server.repo \
https://packages.microsoft.com/config/rhel/9/mssql-server-2022.repo
sudo curl -o /etc/yum.repos.d/msprod.repo \
https://packages.microsoft.com/config/rhel/9/prod.repo
2.3 Install MSSQL 2022 and tools
sudo dnf install -y mssql-server
sudo ACCEPT_EULA=Y dnf install -y mssql-tools18 unixODBC-devel
2.4 Run the initial setup
Pick the Developer edition for non-production; pick Standard or Enterprise for production. Set a strong sa password (uppercase, lowercase, digit, symbol, 8+ characters).
sudo /opt/mssql/bin/mssql-conf setup
sudo systemctl enable --now mssql-server
sudo systemctl status mssql-server
2.5 Add the tools to PATH
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' | sudo tee /etc/profile.d/mssql.sh
source /etc/profile.d/mssql.sh
2.6 Create the miniOrange database and login
Replace <SA_PASSWORD> with the password you set in step 2.4.
sqlcmd -S localhost -U SA -P '<SA_PASSWORD>' -C -Q "
CREATE DATABASE miniorangedb;
GO
CREATE LOGIN moadmin WITH PASSWORD = 'Password123!';
GO
USE miniorangedb;
CREATE USER moadmin FOR LOGIN moadmin;
ALTER ROLE db_owner ADD MEMBER moadmin;
GO
"
Note. MSSQL enforces password complexity by default.
Password123will be rejected;Password123!works.
2.7 Place the MSSQL JDBC driver (derived assumption)
By analogy with the Oracle source flow, MSSQL likely needs the JDBC driver in /opt/miniorange/drivers/. Confirm with miniOrange support.
sudo mkdir -p /opt/miniorange/drivers
cd /tmp
sudo curl -L -o mssql-jdbc.zip \
https://download.microsoft.com/download/8/c/d/8cdfd87a-1684-4731-91a9-2ba182c8b0ad/sqljdbc_12.6.4.0_enu.tar.gz
sudo tar -xzf mssql-jdbc.zip
sudo cp sqljdbc_12.6/enu/jars/mssql-jdbc-12.6.4.jre11.jar /opt/miniorange/drivers/
sudo chmod 644 /opt/miniorange/drivers/mssql-jdbc-12.6.4.jre11.jar
2.8 Open the MSSQL port
sudo firewall-cmd --permanent --add-port=1433/tcp
sudo firewall-cmd --reload
2.9 Verify
sqlcmd -S localhost -U moadmin -P 'Password123!' -C -Q "SELECT name FROM sys.databases;"
miniorangedb should appear.
Values for the /initialize wizard
| Field | Value |
|---|---|
| Database Type | MSSQL |
| Host | 127.0.0.1 |
| Port | 1433 |
| Database name | miniorangedb |
| Username | moadmin |
| Password | Password123! |
Oracle Database 19c on RHEL 9. The flow mirrors the source Oracle Linux 8 + Oracle 19c deployment guide, with one wrinkle: RHEL 9 isn’t on the Oracle 19c preinstall RPM matrix the way Oracle Linux 8 is, so the preinstall step uses the OL8 RPM with --nogpgcheck and --skip-broken.
2.1 Install the Oracle Database preinstall package
sudo dnf install -y \
https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el8.x86_64.rpm \
--nogpgcheck --skip-broken
This creates the oracle user, sets kernel parameters, and configures shell limits. On RHEL 9, this is the closest viable path to the OL8 reference flow.
2.2 Install Oracle 19c
Download oracle-database-ee-19c-1.0-1.x86_64.rpm from Oracle’s site (login required) to the server, then:
cd /opt
sudo dnf localinstall -y oracle-database-ee-19c-1.0-1.x86_64.rpm
2.3 Create the database
sudo /etc/init.d/oracledb_ORCLCDB-19c configure
This creates the structure:
| Item | Value |
|---|---|
| CDB | ORCLCDB |
| PDB | ORCLPDB1 |
| Listener | 1521 |
2.4 Configure Oracle environment variables
sudo -i -u oracle bash <<'BASH'
cat >> ~/.bash_profile <<'PROFILE'
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export ORACLE_SID=ORCLCDB
export PATH=$ORACLE_HOME/bin:$PATH
PROFILE
source ~/.bash_profile
echo $ORACLE_HOME
BASH
2.5 Open the PDB and save state
sudo -i -u oracle bash -c "sqlplus -S / as sysdba" <<'SQL'
STARTUP;
ALTER PLUGGABLE DATABASE ALL OPEN;
ALTER PLUGGABLE DATABASE ALL SAVE STATE;
SHOW PDBS;
SQL
ORCLPDB1 should be in READ WRITE state.
2.6 Start and verify the listener
sudo -i -u oracle bash -c "lsnrctl start || lsnrctl status"
sudo ss -tulnp | grep 1521
2.7 Create the miniOrange Oracle user
sudo -i -u oracle bash -c "sqlplus -S / as sysdba" <<'SQL'
ALTER SESSION SET CONTAINER=ORCLPDB1;
CREATE USER moadmin IDENTIFIED BY Password123;
GRANT CONNECT, RESOURCE TO moadmin;
GRANT DBA TO moadmin;
SQL
Verify connectivity over the service name:
sudo -i -u oracle bash -c "sqlplus moadmin/Password123@//127.0.0.1:1521/ORCLPDB1 <<< 'SELECT 1 FROM dual;'"
2.8 Place the Oracle JDBC driver
This step is required: Oracle’s JDBC driver isn’t bundled in mo-installer because of Oracle’s licensing.
sudo mkdir -p /opt/miniorange/drivers
sudo find /u01/app/oracle -name 'ojdbc8.jar' -print 2>/dev/null | head -1
sudo cp /u01/app/oracle/product/19.0.0/dbhome_1/jdbc/lib/ojdbc8.jar \
/opt/miniorange/drivers/
sudo chmod 644 /opt/miniorange/drivers/ojdbc8.jar
2.9 Open the Oracle port
sudo firewall-cmd --permanent --add-port=1521/tcp
sudo firewall-cmd --reload
Values for the /initialize wizard
Important. Use Service Name, not SID. The IDP schema lives in the PDB (
ORCLPDB1), not the CDB (ORCLCDB).
| Field | Value |
|---|---|
| Database Type | Oracle |
| Host | 127.0.0.1 |
| Port | 1521 |
| SID / Service | Service |
| Service Name | ORCLPDB1 |
| Username | moadmin |
| Password | Password123 |
Erlang + RabbitMQ
RabbitMQ is used by the IDP for internal messaging between microservices. It requires Erlang. Both are installed directly from the official RabbitMQ RPM releases on GitHub.
3.1 Install Erlang 26
sudo dnf install -y \
https://github.com/rabbitmq/erlang-rpm/releases/download/v26.2.5.2/erlang-26.2.5.2-1.el8.x86_64.rpm \
--nogpgcheck
Note. The published Erlang RPM is built for
el8, but installs cleanly on RHEL 9 because of compatible runtime dependencies. There is no currentel9-tagged build from upstream.
3.2 Install RabbitMQ 3.13.7
sudo dnf install -y \
https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.13.7/rabbitmq-server-3.13.7-1.el8.noarch.rpm \
--nogpgcheck
3.3 Enable and start the service
sudo systemctl enable --now rabbitmq-server
sudo systemctl status rabbitmq-server
3.4 Enable the management plugin
sudo rabbitmq-plugins enable rabbitmq_management
sudo systemctl restart rabbitmq-server
3.5 Verify
sudo rabbitmqctl status
sudo ss -tulnp | grep 5672
You should see a listener on :5672 (AMQP) and :15672 (management UI).
Values for the /initialize wizard
| Field | Value |
|---|---|
| RabbitMQ Host | 127.0.0.1 |
| AMQP Port | 5672 |
| Mgmt UI Port | 15672 |
| Default Login | guest / guest |
mo-installer
The miniOrange installer bundles Java 17 and Redis. You don’t install either manually. The installer auto-detects the OS and deploys the IDP services into /opt/tomcat/.
4.1 Download the installer
cd /opt
sudo wget https://miniorange.s3.us-east-1.amazonaws.com/public/installers/mo-installer-5.0.0.zip
sudo unzip mo-installer-5.0.0.zip -d mo-installer-5.0.0
cd /opt/mo-installer-5.0.0
ls -la
You should see:
.env.sh Environment configuration (review before sourcing)
mo-installer.sh Main installer script
moctl/ moctl CLI and bash completion
4.2 Review and source the environment file
less .env.sh
source .env.sh
Note. In v5.0.0,
.env.shdoes not contain database connection details. The DB connection is configured later through the browser UI at/initialize. Source the file as-is.
4.3 Set execute permissions
sudo chmod +x mo-installer.sh moctl/*.sh
4.4 Run the installer
sudo bash mo-installer.sh
Watch the output for failures. The installer covers:
- Java 17 — installed automatically
- Redis — installed and configured automatically
- moctl — installed to
/usr/bin/moctlwith tab completion - IDP services — deployed to
/opt/tomcat/
At the end of the run, the installer will print:
Next step: moctl service start
4.5 Start the four core services
moctl service start
The core services start in this order:
| Service | Port | Purpose |
|---|---|---|
| configserver | 8071 | Configuration |
| eurekaserver | 8070 | Service registry |
| gatekeeper | 8072 | API gateway |
| miniorange | 8080 | Main IDP service |
4.6 Check service status
moctl service status
Only the four core services should be active at this point. Secondary services start after initialisation.
| Symbol | Meaning |
|---|---|
● running | Active and registered in Eureka |
△ registering | Active but not yet registered; wait and recheck |
△ stopped | Inactive |
✗ failed | Failed; check moctl log <service> |
4.7 Open /initialize in a browser
https://<SERVER_IP>/initialize
You will see a self-signed certificate warning. Proceed past it.
Enter the values from the Database section above, plus the Redis and RabbitMQ values from Section 3 (Redis: 127.0.0.1:6379, no password by default).
After the wizard completes, the dashboard loads. Navigate to Settings → Base URL and set it to your final domain:
https://<your-domain>
4.8 Restart all services
This step starts the secondary services that depend on the completed schema.
moctl service restart
Wait 1–2 minutes for everything to register, then verify in the next section.
Verify & Service Enablement
Confirm everything is running and registered. All commands here come from the source v5.0.0 guide.
5.1 Full service status
moctl service status
Every service should show ● running or ● reachable. If anything shows △ registering, wait 30 seconds and re-run.
5.2 Full diagnostics
moctl diagnose
Expected output includes:
Database connectivity reachable
Redis reachable
RabbitMQ reachable
5.3 Individual service status
systemctl status mo-idp-miniorange.service
systemctl status redis
systemctl status rabbitmq-server
5.4 Check all bound ports
sudo ss -tulnp | egrep '8080|8070|8071|8072|6379|5672'
For your DB:
| DB | Port |
|---|---|
| PostgreSQL | 5432 |
| MySQL | 3306 |
| MSSQL | 1433 |
| Oracle | 1521 |
5.5 Preflight
moctl pre checks Java, the DB, Redis, and RabbitMQ reachability in one go.
moctl pre
Quick moctl reference
| Command | Purpose |
|---|---|
moctl service start | Start all services in order |
moctl service stop | Stop all services in reverse order |
moctl service restart | Full ordered restart |
moctl service restart miniorange | Restart one named service |
moctl log <service> -f | Live tail logs |
moctl log <service> --since 1h | Logs from the past hour |
moctl system memory | Per-service RSS memory |
moctl jvm <service> | Heap, threads, open file descriptors |
moctl diagnose ports | Check that core ports are bound |
Common issues
Issue: △ registering after a minute.
The service started but hasn’t completed its handshake with Eureka. Check the gatekeeper log:
moctl log gatekeeper --since 5min
Issue: PostgreSQL peer authentication failed.
You modified pg_hba.conf but didn’t restart. Run sudo systemctl restart postgresql-16.
Issue: SELinux denials in audit.log.
You skipped section 1.5. Set setenforce 0 and re-check getenforce.
Issue: Tomcat stale PID after a crash.
sudo rm -f /opt/tomcat/latest/temp/*.pid
moctl service restart miniorange