How to Secure Prometheus with HTTPS and Password on CentOS 9

By default, Prometheus is open to anyone who knows your IP address. This guide shows you how to lock it down using its native security features. This means you get a login screen and an encrypted connection without needing extra software like Nginx.

✅ Note If you haven't installed Prometheus yet, check out my previous guide on How to Install Prometheus on CentOS Stream 9 before you start securing your server.

What this setup does:

  • Login Security : Adds a username and password.
  • HTTPS Encryption : Protects your data while it travels over the network.
  • OS Hardening :Uses CentOS 9 security layers (SELinux and Systemd) to keep the app isolated.

Step 1 Create a Dedicated User and Folders

Running Prometheus as root is a big security risk. We will create a restricted system user that only has access to its own files.

Bash

sudo useradd --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus/certs /var/lib/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus

    

Step 2 Generate SSL Certificates (HTTPS)

To use https://, you need a certificate. We will create a self-signed one. Replace YOUR_SERVER_IP with your actual server IP.

Bash

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/prometheus/certs/prometheus.key \
  -out /etc/prometheus/certs/prometheus.crt \
  -subj "/C=US/ST=State/L=City/O=IT/CN=prometheus.local" \
  -addext "subjectAltName=DNS:prometheus.local,IP:YOUR_SERVER_IP"

# Lock down the private key so only Prometheus can read it
sudo chmod 600 /etc/prometheus/certs/prometheus.key
sudo chown prometheus:prometheus /etc/prometheus/certs/prometheus.key


    

Step 3 Fix SELinux Permissions

CentOS 9 is very strict about file access. If you skip this, Prometheus will crash because it won't have permission to read the certificates you just made.

Bash

sudo semanage fcontext -a -t prometheus_var_lib_t "/etc/prometheus/certs(/.*)?"
sudo restorecon -Rv /etc/prometheus/certs

    

Step 4 Create your Login Password

We use a tool called htpasswd to hide your password behind a secure hash

Bash

sudo dnf install httpd-tools -y
# Type your password when asked
htpasswd -nB admin

    
Note Copy the result (e.g., admin:$2y$05$...).

Create the Web Security File

sudo vi /etc/prometheus/web-config.yml

YAML

tls_server_config:
  cert_file: /etc/prometheus/certs/prometheus.crt
  key_file: /etc/prometheus/certs/prometheus.key

basic_auth_users:
  admin: "$2y$05$PASTE_YOUR_HASH_HERE"


    
⚠️ Crucial: Secure this file so other users on the server can't see your login hash.
Bash

sudo chown prometheus:prometheus /etc/prometheus/web-config.yml
sudo chmod 600 /etc/prometheus/web-config.yml



    

Step 5 Harden the Systemd Service

We update the service file to use our security settings and add sandboxing to keep your OS safe.

sudo vi /etc/systemd/system/prometheus.service

Ini, TOML

[Unit]
Description=Prometheus Secure
After=network.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
    --config.file=/etc/prometheus/prometheus.yml \
    --storage.tsdb.path=/var/lib/prometheus/ \
    --web.config.file=/etc/prometheus/web-config.yml

# Security isolation
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
ProtectKernelTunables=true

[Install]
WantedBy=multi-user.target

    

Step 6 Update your Configuration

Since Prometheus now requires a password to talk to itself, we must update the main config.

sudo vi /etc/prometheus/prometheus.yml

YAML

scrape_configs:
  - job_name: "prometheus"
    scheme: https
    tls_config:
      # Set to 'true' only for self-signed certs. Use 'false' for Let's Encrypt.
      insecure_skip_verify: true
    basic_auth:
      username: 'admin'
      password: 'YourActualPassword'
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "node_exporter"
    static_configs:
      - targets: ["127.0.0.1:9100"]


    
⚠️ Warning: Never expose Node Exporter (port 9100) to the public internet. Keep it bound to 127.0.0.1.
📢 Secure the file sudo chmod 600 /etc/prometheus/prometheus.yml

Step 7 Lock the Firewall

It is safest to only allow your specific IP address to access the dashboard.

Bash

# Replace YOUR_IP with your actual home/office IP
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="YOUR_IP" port protocol="tcp" port="9090" accept'
sudo firewall-cmd --reload

    
✅ Note If your home internet IP changes, you will need to update this rule to stay connected.

Step 8 Start and Troubleshooting

Apply the changes and check if it’s running:

Bash

sudo systemctl daemon-reload
sudo systemctl enable --now prometheus

    

If it doesn't start, check these:

  • Logs : sudo journalctl -u prometheus -f (Look for "Permission Denied" or YAML errors).
  • SELinux : If you see permission errors, re-run the commands in Step 3.
  • YAML : Ensure there are no tabs in your .yml files; use spaces only.

Conclusion

Setting up HTTPS and Basic Authentication natively is the most efficient way to protect your metrics without the hassle of extra software. By also including SELinux and Systemd hardening, you have ensured that your CentOS Stream 9 server is protected at the operating system level, not just the application level.

Remember that security is an ongoing process. Keep your server updated, rotate your passwords occasionally, and always keep an eye on your logs to ensure everything is running smoothly.

What to Read Next

Ready to take your monitoring stack to the next level? Check out our related guides:

╰┈➤ How to Secure Prometheus with HTTPS and Password
╰┈➤ How to Install Prometheus and Node Exporter

Ready to Deploy Your Monitoring Stack?

You have the knowledge, now get the hardware. Run Prometheus and Node Exporter seamlessly on our high-performance Bare Metal Dedicated Servers. Engineered for 24/7 uptime and real-time data processing.

Deploy Your Dedicated Server Today

Common Mistakes to Avoid

Skipping SELinux Commands On CentOS Stream 9, skipping semanage will prevent Prometheus from reading its SSL certs. The service will fail to start with a Permission Denied error. Always apply the proper context.
Leaving Config Files "World-Readable" Your prometheus.yml contains a plaintext password. Always run chmod 600 so that only the Prometheus user can see the credentials.
Using Tabs in YAML Files YAML files hate tabs. Using a tab instead of spaces for indentation will cause a "mapping values" error, and Prometheus won't start. Use spaces only.
Forgetting HTTPS in Scrape Config Once you switch to HTTPS, you must change the scheme from http to https in your config. Otherwise, Prometheus won't be able to monitor itself.
Exposing Port 9100 Publicly Node Exporter has no built-in password. Never open port 9100 to the public internet. Keep it bound to 127.0.0.1 or use a firewall to restrict access.
Disabling TLS Verification in Production Setting insecure_skip_verify: true is fine for self-signed certs, but in a real production environment, you should use a valid CA and set this to false to prevent Man-in-the-Middle attacks.