Ragnar API Proxy is a simple, lightweight proxy for PierreGode/Ragnar. It was developed with gethomepage/homepage in mind but supports any application that uses HTTP basic authentication headers.
Ragnar is a powerful network scanning tool which can be used for monitoring and vulnerability assessment. It ships with an API enabling retrieval of Ragnar's data which is unsecured by default. If the user enables authentication, API access is authenticated via a Flask session cookie, which is received by the client after POSTing login credentials (username/password) to its authentication endpoint.
This authentication flow is incompatible with stateless clients such as Homepage. A middleware service is required to proxy the API requests and handle session cookie management. That's where Ragnar API Proxy comes in. It enables a client like Homepage to send a request via a HTTP basic authentication header and receive the JSON returned by Ragnar's /api/auth endpoint.
- Simple and lightweight
- Enables stateless clients to authenticate Ragnar API Proxy
- Designed with Homepage in mind
- Supports clients that can send a HTTP Basic Auth header
- Only forwards Ragnar login credentials when a new session cookie is needed
- Supports HTTP/HTTPS Ragnar servers
- Lightweight Docker image for quick deployment and easy integration with Homepage or other applications
.
├── examples
│ ├── docker
│ │ ├── compose-standalone.yml # Standalone Docker deployment
│ │ └── compose-homepage.yml # Docker deployment alongside Homepage
│ └── systemd
│ └── ragnar-api-proxy.service # Systemd service file for non-Docker deployment
├── src
│ ├── __init__.py
│ └── app.py # Main entrypoint
├── tests
│ ├── __init__.py
│ ├── conftest.py # Pytest fixtures
│ └── test_routes.py # Main test module
├── Dockerfile # Docker image definition
├── gunicorn.conf.py # Gunicorn configuration
├── README.md # Documentation
├── requirements-dev.txt # Python dependencies (development/testing)
├── requirements.txt # Python dependencies (production)
├── .dockerignore # Docker image build context exclusions
└── .env.example # Sample environment variables
mkdir /opt/ragnar-api-proxy
cd /opt/ragnar-api-proxygit clone https://github.com/jark-dev/ragnar-api-proxy.git .Copy .env.example to .env.
cp .env.example .envFor all Docker deployments, LISTEN_ADDRESS should be kept at the default value of 0.0.0.0. This applies to configurations where the client service (e.g. Homepage) is deployed within the same Docker network as Ragnar API Proxy, as well as configurations where the client service is deployed outside the Docker network.
Note
This listen address applies only to the Flask app running inside the Docker container. The listen address of the Docker container is specified in the Compose file via the expose or ports attributes (next section).
# .env
LISTEN_ADDRESS=0.0.0.0The default LISTEN_PORT of 5000 works fine for most setups, but this can be modified if desired.
# .env
LISTEN_PORT=5000Update RAGNAR_BASE_URL. Be sure to include the leading http:// or https://. Also include the trailing port (e.g. :8000) if your setup does not use standard HTTP(S) ports (80 for HTTP and 443 for HTTPS). Port 8000 is standard for most Ragnar installations. Do not include a trailing slash.
# .env
RAGNAR_BASE_URL=http://ragnar.example.org:8000If using Ragnar with a custom HTTPS certificate, uncomment REQUESTS_CA_BUNDLE and set its value to the path of your custom certificate chain (including the CA certificate and leaf certificate). If using HTTP or a non-custom HTTPS certificate (e.g. Let's Encrypt), leave REQUESTS_CA_BUNDLE commented out (or delete it).
#.env
RAGNAR_BASE_URL=https://ragnar.example.org:8000
REQUESTS_CA_BUNDLE=/path/to/custom-ca-chain.pemImportant
If the client service runs on a remote host, it is strongly recommended to use HTTPS as HTTP Basic Auth transmits Ragnar login credentials in base64-encoded cleartext (i.e. unencrypted). If HTTP absolutely must be used, it is highly recommended to run Ragnar API proxy and the client service on the same host to minimize the potential attack surface.
Copy the appropriate Compose file example from the /examples subdirectory to the root of the working directory as compose.yml.
For deployment alongside Homepage in a single Compose file, copy the compose-homepage.yml example.
cp ./examples/compose-homepage.yml compose.ymlReplace the homepage section in the services block with your configuration.
# compose.yml
services:
ragnar-api-proxy:
build: .
container_name: ragnar-api-proxy
env_file:
- .env
restart: unless-stopped
expose:
- ${LISTEN_PORT}
homepage:
### REPLACE WITH YOUR HOMEPAGE CONFIGURATION ###
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
environment:
HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts
PUID: 1000 # optional, your user id
PGID: 1000 # optional, your group id
ports:
- 3000:3000
volumes:
- /path/to/config:/app/config # Make sure your local config directory exists
- /var/run/docker.sock:/var/run/docker.sock:ro # optional, for docker integrations
restart: unless-stoppedFor standalone deployment, copy the compose-standalone.yml example.
cp ./examples/compose-standalone.yml compose.ymlBy default, the container will listen only on localhost, which is preferred when the client is running on the same host. If the client runs on a remote host, either replace the leading 127.0.0.1 in the ports attribute with the desired listen address, or delete this line and uncomment the line below, which listens on all addresses.
# compose.yml
services:
ragnar-api-proxy:
build: .
container_name: ragnar-api-proxy
env_file:
- .env
restart: unless-stopped
ports:
- "127.0.0.1:${LISTEN_PORT}:${LISTEN_PORT}" # use when client runs on local host
# - "${LISTEN_PORT}:${LISTEN_PORT}" # uncomment and use when client runs on remote hostCreate and start the service using Docker Compose.
docker compose up -dmkdir /opt/ragnar-api-proxy
cd /opt/ragnar-api-proxygit clone https://github.com/jark-dev/ragnar-api-proxy.git .python -m venv .venv
source .venv/bin/activatepip install -r requirements.txtCopy .env.example to .env.
cp .env.example .envConfigure the LISTEN_ADDRESS according to the desired setup:
| Location of Client Service | LISTEN_ADDRESS |
|---|---|
| Same host as Ragnar API Proxy | 127.0.0.1 |
| Remote host | 0.0.0.0 (or specific IP address) |
# .env
LISTEN_ADDRESS=0.0.0.0The default LISTEN_PORT of 5000 works fine for most setups, but this can be modified if desired.
# .env
LISTEN_PORT=5000Update RAGNAR_BASE_URL. Be sure to include the leading http:// or https://. Also include the trailing port (e.g. :8000) if your setup does not use standard HTTP(S) ports (80 for HTTP and 443 for HTTPS). Port 8000 is standard for most Ragnar installations. Do not include a trailing slash.
# .env
RAGNAR_BASE_URL=http://ragnar.example.org:8000If using Ragnar with a custom HTTPS certificate, uncomment REQUESTS_CA_BUNDLE and set its value to the path of your custom certificate chain (including the CA certificate and leaf certificate). If using HTTP or a non-custom HTTPS certificate (e.g. Let's Encrypt), leave REQUESTS_CA_BUNDLE commented out (or delete it).
#.env
RAGNAR_BASE_URL=https://ragnar.example.org:8000
REQUESTS_CA_BUNDLE=/path/to/custom-ca-chain.pemImportant
If the client service runs on a remote host, it is strongly recommended to use HTTPS as HTTP Basic Auth transmits Ragnar login credentials in base64-encoded cleartext (i.e. unencrypted). If HTTP absolutely must be used, it is highly recommended to run Ragnar API proxy and the client service on the same host to minimize the potential attack surface.
Ragnar API Proxy can be executed in the command line via the following command:
gunicorn "src.app:create_app()"The command above works fine for testing, but for production, it is recommended (and more convenient) to run Ragnar API Proxy as a daemon. This can be achieved by creating a systemd unit. Copy the systemd service file example to /etc/systemd/system.
cp ./examples/systemd/ragnar-api-proxy.service /etc/systemd/system/ragnar-api-proxy.serviceThe default service file works out of the box, assuming that the working directory is /opt/ragnar-api-proxy. If a custom working directory was used, replace all instances of /opt/ragnar-api-proxy with the appropriate path in WorkingDirectory= and ExecStart=.
Additionally, the service will run as www-data by default. This is appropriate for systems where Ragnar API Proxy is the only application running as this user. If the system has other applications also running as www-data, consider creating a dedicated user for Ragnar API Proxy to maximize isolation. Replace www-data with the custom user in User= and Group=.
# /etc/systemd/system/ragnar-api-proxy.service
[Unit]
Description=Gunicorn instance serving Ragnar API Proxy
After=network.target
[Service]
User=your-username
Group=your-username
WorkingDirectory=/path/to/ragnar-api-proxy
ExecStart=/path/to/ragnar-api-proxy/.venv/bin/gunicorn --config /path/to/ragnar-api-proxy/gunicorn.conf.py --no-control-socket "src.app:create_app()"
Restart=always
[Install]
WantedBy=multi-user.target
Ensure the configured user has read permissions for the working directory. The easiest way to achieve this is to recursively chown the working directory. Remember to update the user and group name to the custom user if the default www-data is not used.
chown -R www-data:www-data /opt/ragnar-api-proxyEnable and start the service.
systemctl daemon-reload
systemctl enable ragnar-api-proxy.service
systemctl start ragnar-api-proxy.service
systemctl status ragnar-api-proxy.service # verify service started successfullyCreate a new entry in services.yaml for Ragnar using the template below. Update the Ragnar & Ragnar API Proxy URLs to reflect your configuration.
Note
The href and ping fields should point to your Ragnar instance, and url should point to your Ragnar API Proxy instance.
# /path/to/homepage/config/services.yaml
- Ragnar:
icon: https://raw.githubusercontent.com/PierreGode/Ragnar/refs/heads/main/resources/images/static/ragnar1.bmp
href: http://<RAGNAR_IP_or_FQDN>:8000 # update per your setup
description: Internal network monitoring system
ping: <RAGNAR_IP_or_FQDN> # update per your setup
widget:
type: customapi
url: http://<RAGNAR_API_PROXY_IP_or_FQDN>:5000/proxy # update IP/FQDN and port per your setup
username: "{{HOMEPAGE_VAR_RAGNAR_USERNAME}}"
password: "{{HOMEPAGE_VAR_RAGNAR_PASSWORD}}"
mappings:
- field: level
label: Level
- field: scanned_network_count
label: Scanned Networks
- field: target_count
label: Targets
- field: vulnerability_count
label: VulnerabilitiesThe configuration above is just an example, but the mappings can be replaced with any field that is available in Ragnar's /api/status endpoint. For a complete list of available fields, navigate to http://<RAGNAR_IP_or_FQDN>:8000/api/status in your web browser.
Add Ragnar login credentials to the Homepage .env file (NOT THE RAGNAR API PROXY .env FILE).
# /path/to/homepage/.env
HOMEPAGE_VAR_RAGNAR_USERNAME=your_username
HOMEPAGE_VAR_RAGNAR_PASSWORD=your_password
Homepage must be restarted to apply updates to the environment variables.
If running Homepage via Docker:
docker compose down && docker compose up -dIf running Homepage via systemd service:
systemctl restart homepage.service # update service name as appropriateCurrently, official configuration documentation only exists for Homepage, but Ragnar API Proxy is compatible with any service that uses HTTP Basic Auth headers to access external APIs. The high-level configuration steps are as follows:
- Point the service to Ragnar API Proxy's endpoint
- Default:
http://ragnar.example.org:8000/proxy
- Default:
- Configure environment file with Ragnar login credentials
- Specify fields to request from Ragnar's
/api/statusendpoint- E.g. Level, Scanned Networks, Targets, Vulnerability Count, etc.
- Add dedicated API endpoint for health checks
- Create Docker image for faster initial deployment
- Add documentation for other services (e.g. Homarr, Dashy, Heimdall, etc.)