> For the complete documentation index, see [llms.txt](https://help.sentinelsoftware.com/sentinel-help-center/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.sentinelsoftware.com/sentinel-help-center/installation-and-updates/sentinel-install-guide.md).

# Sentinel Install Guide

### Before you start: terminal basics

You will be connecting to the server over SSH (using a tool like PuTTY, Terminal, or a similar SSH client) and typing commands into a black screen called the **terminal**. A few things to know:

* **Commands are case-sensitive.** `Sentinel` and `sentinel` are different.
* **Type or paste commands exactly as written**, including all punctuation (`-`, `/`, `.`, quotes). If a screenshot or copy/paste changes a character (e.g. a smart quote `'` instead of a plain `'`), the command may fail with a confusing error.
* **Multi-line commands** (ones with a `\` at the end of a line, or wrapped in `<< 'EOF' ... EOF`) must be pasted as one block, all at once. If you only paste part of it, your terminal will show a `>` prompt waiting for the rest — press `Ctrl` + `C` to cancel and start over if that happens.
* **You need "root" (administrator) access** for almost every command below. If a command fails with `Permission denied`, you are not running as root — see the next section.
* **To edit a text file directly** (a few steps ask you to), this guide uses `nano`, a simple in-terminal editor:
  * Move the cursor with arrow keys.
  * Type to insert text.
  * Press `Ctrl` + `O` then `Enter` to save.
  * Press `Ctrl` + `X` to exit.

#### Becoming root

If you logged in as a regular user, switch to root before continuing:

```
sudo -i
```

Enter your password if prompted. Your terminal prompt should now end in `#` instead of `$`, confirming you are root. All commands in this guide assume you are root from this point forward.

### Fill in your values first

Before you begin, decide on the values below and **write them down somewhere** (a text file, notepad, password manager). You will reuse the exact same values in multiple steps — using a different password or name in one step than another is one of the most common causes of a broken install.

| What                          | Example used in this guide | Your actual value              |
| ----------------------------- | -------------------------- | ------------------------------ |
| Database name                 | `sentinel`                 | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |
| Database username             | `dean`                     | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |
| Database password             | `SetPasswordHere`          | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |
| Your domain name for Sentinel | `sentinel.yourcompany.com` | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |
| Your Sentinel license key     | `YOUR-LICENSE-KEY-HERE`    | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |
| Admin login email             | `admin@yourdomain.com`     | \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ |

Everywhere this guide shows one of the **example** values above in a command, replace it with **your actual value** from the table. This guide will always show example values in this exact same style so they're easy to spot.

You will also need, before starting:

* The Sentinel `.jar` installation file, given to you by Sentinel support.
* Your SSL certificate files for your domain (two files: a certificate and a private key), either from your IT/security team or a certificate authority. If you don't have these yet, stop here and obtain them before continuing — step 11 needs them.
* Confirmation that your domain name's DNS already points at this server's IP address.

### Prerequisites checklist

* A Virtual Machine running Oracle Linux, CentOS, or RHEL version 9 (64-bit)
* Root access (see above)
* Domain name already pointing at this VM (via DNS)
* SSL certificate files for that domain
* The Sentinel software requires **Java 21 or newer** and **PostgreSQL 17 or newer** — this guide installs both correctly from scratch; you don't need to source these separately.
* This server must be able to reach the internet (specifically `license.sentinelsoftware.com` on ports 80 and 443) — most VMs can do this by default, but if your organization has a strict outbound firewall or proxy, mention this requirement to whoever manages it now, so it isn't a surprise in step 8.

### Step 1: Create the application folder

```
mkdir -p /opt/sentinel
```

This creates a folder where all Sentinel files will live. No output means it worked.

### Step 2 (optional/advanced): Use a separate disk for the database

**Skip this entire step if your server has one single disk** (most small/standard VMs do) — go straight to Step 3. Only follow this step if you were specifically given a second disk or volume to store the database on.

If you're unsure whether you have a second disk, check with this command:

```
lsblk
```

This lists all disks attached to the server. If you only see one disk (usually named `sda`), skip to Step 3. If you see a second, unused disk (e.g. `sdb` with no partitions), continue:

```
# Format the entire second disk with a filesystem (replace sdb if your disk has a different name)mkfs.xfs /dev/sdb# Create a mount point and mount itmkdir -p /data01mount /dev/sdb /data01# Make this mount survive a reboot: find the disk's unique IDblkid /dev/sdb
```

The last command prints a line containing `UUID="....."`. Copy that UUID value, then open the filesystem table file for editing:

```
nano /etc/fstab
```

Add this as a new line at the bottom (replace `<uuid-here>` with the UUID you copied), then save (`Ctrl+O`, `Enter`) and exit (`Ctrl+X`):

```
UUID=<uuid-here>  /data01  xfs  defaults  0 0
```

Finally, create a folder for the database and link it into place:

```
mkdir -p /data01/pgdata17chown postgres:postgres /data01/pgdata17ln -s /data01/pgdata17 /opt/sentinel/pgdata17
```

### Step 3: Install Java

```
dnf install -y java-21-openjdk.x86_64
```

You'll see a lot of text scroll by ending in `Complete!` — that means it succeeded.

Now confirm it installed correctly:

```
java -version
```

**You must see `21` somewhere in the output** (e.g. `openjdk version "21.0.x"`). If you see a lower number, do not continue — something is wrong with the install and Sentinel will not run correctly on an older Java version.

### Step 4: Install PostgreSQL (the database)

```
# Add PostgreSQL's official software sourcednf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm# Turn off the older built-in version so the correct one installsdnf -qy module disable postgresql# Install PostgreSQL version 17dnf install -y postgresql17-server postgresql17-contrib
```

Each command should end with `Complete!`.

#### If you did Step 2 (separate disk) — set up a custom database location

**If you skipped Step 2, skip this box and go to "Otherwise" below.**

```
cp /usr/lib/systemd/system/postgresql-17.service /etc/systemd/system/postgres-snt.servicesed -i 's+Environment=PGDATA=.*+Environment=PGDATA=/opt/sentinel/pgdata17/+g' /etc/systemd/system/postgres-snt.servicesystemctl daemon-reloadchown postgres:postgres /opt/sentinel/pgdata17 -Rchmod 700 /opt/sentinel/pgdata17/usr/pgsql-17/bin/postgresql-17-setup initdb postgres-sntsystemctl enable postgres-sntsystemctl start postgres-sntsystemctl status postgres-snt
```

The last command should show a line reading `Active: active (running)` in green. Press `q` to exit the status screen. **Everywhere else in this guide, wherever you see `postgres-snt` used as the service name, keep using `postgres-snt`.**

#### Otherwise — use the standard default location

```
systemctl enable --now postgresql-17systemctl status postgresql-17
```

Again, look for `Active: active (running)` in green, then press `q`. **Everywhere else in this guide, wherever you see `postgres-snt` used as the service name, use `postgresql-17` instead** since you're using the default setup.

> The rest of this guide uses `postgres-snt` in examples for brevity — substitute `postgresql-17` throughout if you used the default location.

#### Step 4a: Basic database security settings

Find your database's data folder (this is `/opt/sentinel/pgdata17` if you did Step 2, or `/var/lib/pgsql/17/data` if you used the default):

```
echo "listen_addresses = '127.0.0.1'" >> /var/lib/pgsql/17/data/postgresql.confecho "password_encryption = scram-sha-256" >> /var/lib/pgsql/17/data/postgresql.conf
```

(If you did Step 2, replace `/var/lib/pgsql/17/data` in both lines above with `/opt/sentinel/pgdata17`.)

#### Step 4b: Allow Sentinel to connect

Open the connection permissions file for editing (adjust the path the same way as above if you did Step 2):

```
nano /var/lib/pgsql/17/data/pg_hba.conf
```

Scroll to the bottom using the arrow keys, and add this new line (using **your actual database name and username** from the table you filled in earlier — this example uses `sentinel` and `dean`):

```
host  sentinel  dean  127.0.0.1/32  scram-sha-256
```

Save (`Ctrl+O`, `Enter`) and exit (`Ctrl+X`). Then apply the change:

```
systemctl restart postgres-snt
```

(Use `systemctl restart postgresql-17` instead if you used the default location.)

#### Step 4c: Create the database, the username, and the password

Replace `sentinel`, `dean`, and `SetPasswordHere` below with **your actual values** from the table:

```
sudo -u postgres createdb sentinelsudo -u postgres createuser deansudo -u postgres psql -c "ALTER USER dean WITH ENCRYPTED PASSWORD 'SetPasswordHere';"sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE sentinel TO dean;"sudo -u postgres psql -d sentinel -c "GRANT ALL ON SCHEMA public TO dean;"sudo -u postgres psql -d sentinel -c "CREATE EXTENSION IF NOT EXISTS btree_gin;"
```

Each `psql -c` command should print `ALTER ROLE`, `GRANT`, or `CREATE EXTENSION` confirming success — if you instead see a line starting with `ERROR:`, stop and re-check the command for typos before continuing.

**Now test the connection** — this is the most important check in this whole step:

```
psql -U dean --host 127.0.0.1 -d sentinel -c "SELECT 1;"
```

(Replace `dean` and `sentinel` with your actual username/database name.) You will be prompted for the password you set above. If it works, you'll see:

```
 ?column?----------        1(1 row)
```

**If instead you see `password authentication failed` or `could not connect`, do not proceed to later steps** — go back and re-check Steps 4a–4c; a mistake here will cause confusing failures much later in the install.

### Step 5: Get the Sentinel software file onto the server

You need to transfer the `.jar` file you were given (something like `sentinel-25.1.2445-standalone.jar`) into the `/opt/sentinel` folder on this server. Pick **one** of these methods:

**Option A — if you have the file on your own computer**, use a file-transfer tool like WinSCP (Windows) or Cyberduck (Mac) to connect to the server with the same login you use for SSH, and drag the `.jar` file into `/opt/sentinel`.

**Option B — if the file is hosted at a URL you were given**, download it directly on the server:

```
cd /opt/sentinelwget "PASTE_THE_DOWNLOAD_URL_HERE"
```

Once the file is in `/opt/sentinel`, confirm it's there and note its exact filename:

```
ls -lh /opt/sentinel/*.jar
```

Now create a shortcut named `sentinel.jar` pointing at it — **replace `sentinel-25.1.2445-standalone.jar` below with the exact filename you just saw**:

```
cd /opt/sentinelln -sf sentinel-25.1.2445-standalone.jar sentinel.jar
```

### Step 6: Set up Sentinel as a background service (but don't start it yet)

This creates a configuration so Sentinel runs automatically and restarts itself if it ever crashes. Paste this entire block as one piece — replace `sentinel`, `dean`, and `SetPasswordHere` with your actual values from the table:

```
cat > /etc/systemd/system/sentinel.service << 'EOF'[Unit]Description=Sentinel Server daemonAfter=network.target postgres-snt.service[Service]Type=simpleRestart=alwaysRestartSec=3Environment=PORT=8080Environment=DB_NAME=sentinelEnvironment=DB_USER=deanEnvironment=DB_PASSWORD=SetPasswordHereEnvironment=DB_HOST=127.0.0.1Environment=DB_PORT=5432ExecStart=/usr/bin/java -Xmx8g -Xms4g -jar /opt/sentinel/sentinel.jar start -P 8080 -H 0.0.0.0[Install]WantedBy=multi-user.targetEOFsystemctl daemon-reloadsystemctl enable sentinel.service
```

No visible errors means this worked.

> **Important — do not run `systemctl start sentinel.service` yet.** The next step (Step 7) must run first, or Sentinel will crash repeatedly with a database error. This is the single most common mistake in this install — Steps 6 and 7 must happen in this exact order.

### Step 7: Initialize Sentinel's database (the step that actually builds everything)

This step creates all of Sentinel's internal database tables and registers your license. It is the step most likely to have a typo cause a confusing failure, so go slowly and check the output at each command.

Replace `sentinel`, `dean`, `SetPasswordHere`, and `YOUR-LICENSE-KEY-HERE` with your actual values:

```
cd /opt/sentineljava -Ddb-host=127.0.0.1 -Ddb-port=5432 -Ddb-name=sentinel -Ddb-user=dean -Ddb-password=SetPasswordHere \  -jar sentinel.jar register --license-key "YOUR-LICENSE-KEY-HERE" 2>&1 | tee /tmp/register-output.log
```

> **Why this exact command form?** You may see other guides show this using `DB_HOST=...` written before `java` instead of `-Ddb-host=...` after it. Both look reasonable, but in practice the `DB_HOST=...` style has been observed to silently fail to reach the app's settings — the app then quietly tries to connect to a meaningless placeholder address instead of your real database, and hangs for a long time before failing with a confusing error. Using `-Ddb-host=...` (exactly as written above) has been reliable. Always use this exact style for the commands in this step and the next.

This will print many lines of text — that's normal and expected, it's creating dozens of database tables one by one. You may see a couple of lines containing the word `WARN` — those are expected on a brand-new database and are not a problem.

**Scroll to the very last two lines of the output. You must see:**

```
Migrations DONEClient registered with license key
```

If you don't see both of those exact lines at the end, something failed — do not continue to the next command. Instead, read through `/tmp/register-output.log` for a line containing `ERROR` or `Exception`, and stop here to get help before proceeding, quoting that line.

**Now double-check it actually worked** by asking the database directly (replace `dean`/ `sentinel` with your values):

```
psql -U dean --host 127.0.0.1 -d sentinel -c "SELECT * FROM client;"
```

You should see one row of output (not `(0 rows)`). If you see `(0 rows)`, the previous command did not actually succeed even if it looked like it did — get help before continuing.

#### Create your admin login

Still using your actual values, and a real email address you'll use to log in:

```
java -Ddb-host=127.0.0.1 -Ddb-port=5432 -Ddb-name=sentinel -Ddb-user=dean -Ddb-password=SetPasswordHere \  -jar sentinel.jar create_user --email "admin@yourdomain.com" 2>&1 | tee /tmp/create-user-output.log
```

Look for a line near the end that says:

```
Admin user created with password:SOMETHING
```

**Copy that password down right now** — this is the only time it will be shown. You'll use it to log in for the first time once the site is live.

### Step 8: Confirm this server can reach the license server

Sentinel needs to check in with its licensing server over the internet every time someone logs in. Test that now, before going further:

```
curl -4 -v --max-time 10 https://license.sentinelsoftware.com
```

**If this shows any lines starting with `<` or `HTTP`, or text mentioning a certificate**, the connection succeeded — you're good, move to Step 9.

**If instead the command just sits there for about 10 seconds and then prints something like `Connection timed out`**, this server's network is blocking the connection. This is not something you can fix from inside Sentinel's configuration — you (or whoever manages this server's network/firewall/security settings) need to allow **outgoing** connections from this server to `license.sentinelsoftware.com` on ports 80 and 443. Without this fixed, **every login attempt will fail later with a confusing "License is not valid" message**, even with the correct password. Get this resolved before moving on if possible; if you can't resolve it immediately, continue with the rest of the setup and revisit this before expecting logins to work.

### Step 9: Start Sentinel

```
systemctl start sentinel.servicesystemctl status sentinel.service
```

Look for `Active: active (running)` in green. Press `q` to exit the status screen. Now watch the live log for about 30 seconds to make sure nothing is crashing:

```
journalctl -u sentinel.service -f
```

If you see it settle down without repeating error messages or restarting, press `Ctrl+C` to stop watching, and continue. If you see the same error repeating every few seconds, stop here and get help, including a copy of the repeating error text.

### Step 10: Set the correct time

Accurate time matters for Sentinel to work correctly, and the server's time zone should usually match the time zone of the systems it's monitoring.

```
dnf install -y chronysystemctl enable --now chronydchronyc tracking
```

The last command should print several lines of information without any obvious error. To set the time zone (replace `America/New_York` with the correct zone for your organization — ask if unsure):

```
timedatectl set-timezone America/New_York
```

### Step 11: Set up the web address and secure connection (NGINX)

```
dnf install -y nginx
```

You need your two SSL certificate files uploaded to this server first — use the same file-transfer method from Step 5 to copy them somewhere like `/etc/ssl/sentinel/`:

```
mkdir -p /etc/ssl/sentinel# then transfer your certificate file and private key file into that folder
```

Now create the web server configuration — replace `sentinel.yourcompany.com` with your actual domain name, and the two certificate file paths with your actual uploaded filenames:

```
cat > /etc/nginx/conf.d/sentinel.conf << 'EOF'server {    listen 80;    server_name sentinel.yourcompany.com;    return 301 https://$host$request_uri;}server {    listen 443 ssl;    server_name sentinel.yourcompany.com;    ssl_certificate     /etc/ssl/sentinel/your-certificate.crt;    ssl_certificate_key /etc/ssl/sentinel/your-private-key.key;    client_max_body_size 100M;    location / {        proxy_pass http://127.0.0.1:8080;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_set_header X-Forwarded-Proto $scheme;    }}EOF
```

Check the configuration for mistakes before turning it on:

```
nginx -t
```

You must see:

```
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

If you see an error instead, re-check the domain name and certificate file paths you typed above. Once it passes, turn everything on:

```
systemctl enable nginxsystemctl start nginx
```

Open the firewall so the outside world can reach the site over HTTP/HTTPS:

```
firewall-cmd --permanent --add-service=httpfirewall-cmd --permanent --add-service=httpsfirewall-cmd --reload
```

### Step 12: Final check — visit the site

Test the connection from the server itself first:

```
curl -k -i https://sentinel.yourcompany.com/_ping
```

(Replace with your actual domain.) You should see `HTTP/1.1 200 OK` near the top, and the word `pong` at the very end.

If that works, open a web browser on your own computer and go to `https://sentinel.yourcompany.com` (your actual domain). Log in with the admin email and the temporary password you saved in Step 7.

### If login doesn't work

Compare the exact wording of the error message on the login screen to this table:

| What the error says                             | What it means                                                                                                   | What to do                                                                                                                                                           |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Something about the email not being confirmed   | Account setup issue                                                                                             | Re-run the `create_user` command from Step 7                                                                                                                         |
| Something about the account being locked        | Too many failed attempts, or an admin locked it                                                                 | Wait and try again, or get help unlocking it                                                                                                                         |
| Something about a password reset being required | The account needs a new password set                                                                            | Re-run the `create_user` command from Step 7 — this safely resets the password                                                                                       |
| "User name or Password does not match"          | Simply a wrong password                                                                                         | Double check you copied the temp password from Step 7 exactly, with no extra spaces; if unsure, re-run the `create_user` command from Step 7 to get a fresh password |
| "License is not valid" or "License is expired"  | **This is almost never a real credentials problem** — it means this server still can't reach the license server | Go back to Step 8 and get the outbound network connection fixed                                                                                                      |

### If something in this guide gave an unexpected error

1. Copy the exact error message — do not paraphrase it.
2. Note which step number you were on.
3. Note the exact command you ran, character for character.

With those three things, get help from Sentinel support or whoever provided this guide — having the exact text dramatically speeds up diagnosis.
