River-Guide is a simple web interface for managing cloud instances.
Currently, AWS EC2 instances, AWS RDS instances and Azure Virtual Machines are
supported. AWS RDS management is turned off by default, but can be enabled by
setting the --rds flag at application start up.
River-Guide utilizes the respective cloud provider's APIs to provide listing and start/stop capabilities of instances through a web interface. River-Guide also supports tag-based filtering of instances, enabling you to only display instances of interest. Configuration can be provided through command line flags, a configuration file, or environment variables.
The simplest way to get started is using the pre-built binaries.
if [[ $(uname -m) == aarch64 ]]; then
GOARCH=arm64
else
GOARCH=amd64
fi
curl -LO https://github.com/frgrisk/river-guide/releases/latest/download/river-guide-linux-$GOARCH
chmod +x river-guide-linux-$GOARCH
sudo cp river-guide-linux-$GOARCH /usr/local/bin/river-guideOr, if you have Go installed, you can install it using Go.
go install github.com/frgrisk/river-guide@latestFor the application to work, it needs to have the necessary permissions to list, start and stop instances. The application will use the credentials configured on the machine it's running on. Approaches to authentication vary by cloud provider and whether you're temporarily testing the application or deploying it in a production environment.
For temporary testing, a common pattern is to use the AWS CLI or Azure
CLI to configure your credentials. For AWS, run aws configure and
provide your access key and secret key (see Get your AWS access keys).
You can also simply set the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
and AWS_SESSION_TOKEN environment variables in your session if you have them.
For Azure, you can run az login and follow the instructions to authenticate.
For production deployments, you can use instance profiles to pass an IAM role for AWS or managed identities for Azure. With either cloud provider, the application will automatically use the credentials configured on the machine it's running on.
For AWS EC2, the following Amazon EC2 permissions are required:
ec2:DescribeInstancesec2:StartInstancesec2:StopInstancesec2:DescribeInstanceStatus
For AWS RDS, the following Amazon RDS permissions are required:
rds:DescribeDBInstancesrds:StartDBInstancerds:StopDBInstance
For Azure, the following Microsoft.Compute permissions are required:
Microsoft.Compute/virtualMachines/readMicrosoft.Compute/virtualMachines/instanceView/readMicrosoft.Compute/virtualMachines/start/actionMicrosoft.Compute/virtualMachines/deallocate/action
This section includes examples of how to use the application. See the Flags section for a complete list of flags.
Start the server with the default settings, which will listen on port 3000 and use AWS as the cloud provider, and display all instances.
river-guideStart the server with RDS support enabled.
river-guide --rdsStart the server with a custom port and title.
river-guide --port 8080 --title "My Custom Title"Query instances in a different region and filter on instances that have both tag key "Environment" and value "dev" and tag key "DashboardManageable" and value "true".
AWS_REGION=us-west-2 river-guide --tags "Environment=dev,DashboardManageable=true"Use the Azure cloud provider and filter on instances in the "my-resource-group" resource group having both tag key "Environment" and value "dev" and tag key "DashboardManageable" and value "true".
river-guide --provider azure \
--tags "Environment=dev,DashboardManageable=true" \
--resource-group-name "my-resource-group" \
--subscription-id "00000000-0000-0000-0000-000000000000"The application accepts several flags:
--config: path to configuration file (default is$HOME/.river-guide.yaml).-p, --port: port to listen on (default is3000).--path-prefix: path prefix for the application (default is/). This can be useful when running the application behind a reverse proxy.--provider: cloud provider to use (default isaws).--resource-group-name: filter instances based on their resource group membership (only used with the Azure provider).--subscription-id: subscription ID to use (required for Azure).-t, --tags: filter instances using tag key-value pairs (e.g.,Environment=dev,Name=dev.example.com).--title: title to display on the web page (default is "Environment Control").--accent-color: accent color for buttons and highlights (default is "#93C30B").--background-color: background color (default is "#244A66").--logo: URL for logo image on login page (used as<img src>, not read from disk) (optional).--favicon: path to favicon (default is embedded favicon).--rds: enable support to control RDS instances (default isfalse).--oidc-issuer: OIDC issuer URL (optional)--oidc-client-id: OIDC client ID (optional)--oidc-client-secret: OIDC client secret (optional)--oidc-redirect-url: OIDC redirect URL (optional)--oidc-groups: comma-separated list of allowed OIDC groups (optional)--oidc-scopes: comma-separated list of OIDC scopes to request (optional, defaults to "openid,profile,email" plus "groups" if --oidc-groups is set)--oidc-log-claims: comma-separated list of OIDC claims to include in request logs (optional, defaults to "sub")--session-secret: session secret key (hex-encoded, 64 characters). Required for Lambda deployments (which use CookieStore). Non-Lambda deployments use FilesystemStore, so a shared secret alone does not provide cross-instance session consistency without shared storage or sticky sessions.--session-max-age: session cookie lifetime in seconds (default is 86400 = 24 hours).--tls-cert: path to TLS certificate file (enables HTTPS).--tls-key: path to TLS private key file (requires--tls-cert).
The application can also use a configuration file for setting the parameters.
The configuration file should be in the YAML format. By default, the
application will look for a .river-guide.yaml file in the home directory.
The structure of the file should look something like this:
port: 3000
tags:
Environment: dev
Name: dev.example.com
title: Environment Control
accent-color: "#93C30B"
background-color: "#244A66"
logo: "https://example.com/logo.png" # Optional: URL used as <img src>, not read from disk
favicon: "/path/to/favicon"
session-max-age: 86400 # Session lifetime in seconds (24 hours)Warning
The configuration file uses Viper, which
lowercases all keys including
tag names. If your cloud provider tags are case-sensitive (e.g.,
Environment vs environment), use the --tags flag or the
RIVER_GUIDE_TAGS environment variable instead, which preserve the original
casing.
In addition to flags and the configuration file, you can also use
environment variables to set parameters. The application will automatically
look for any environment variables beginning with RIVER_GUIDE_. For
instance, to set the title, you could use the following command:
export RIVER_GUIDE_TITLE="My Custom Title"For map values like tags, use JSON format:
export RIVER_GUIDE_TAGS='{"Environment":"dev","DashboardManageable":"true"}'River Guide can optionally protect the UI with an OIDC login. Set the following flags (or their configuration equivalents) to enable authentication:
--oidc-issuer: the OIDC issuer URL--oidc-client-id: the client ID registered with the issuer--oidc-client-secret: the client secret for the client ID--oidc-redirect-url: redirect URL configured for the client--oidc-groups: comma-separated list of groups allowed to access the UI (optional)--oidc-scopes: comma-separated list of OIDC scopes to request (optional)--oidc-log-claims: comma-separated list of OIDC claims to include in request logs (optional)
All four of the issuer, client ID, client secret, and redirect URL must be provided for authentication to be enabled. The redirect URL must exactly match the value configured for your OIDC client.
If --oidc-groups is omitted, users from any group are allowed. If --oidc-scopes is omitted, the default scopes are "openid,profile,email" (plus "groups" if --oidc-groups is set). You can override the scopes entirely by providing custom values. If --oidc-log-claims is omitted, only the "sub" (subject) claim is logged with requests.
Example YAML configuration:
oidc-issuer: https://auth.example.com
oidc-client-id: my-app
oidc-client-secret: super-secret
oidc-redirect-url: https://my-app.example.com/callback
oidc-groups:
- admins
- operators
# Optional: override default scopes
oidc-scopes:
- openid
- profile
- email
# Optional: customize claims shown in logs (defaults to sub)
oidc-log-claims:
- email
- nameFor AWS Lambda deployment, you must provide a session secret to ensure session consistency across Lambda instances:
# Generate a session secret
openssl rand -hex 32
# Set as environment variable
export RIVER_GUIDE_SESSION_SECRET=1a38fb587ba3a0a88d4d9a5081a594f014a263cd49829ba15d75d09e2b234480
# Or pass as flag
river-guide --session-secret 1a38fb587ba3a0a88d4d9a5081a594f014a263cd49829ba15d75d09e2b234480Important: The session secret must be exactly 64 hex characters (32 bytes). Without a consistent session secret, users will be logged out between Lambda cold starts.
The application provides the following endpoints:
GET /: The main interface for managing cloud instances (shows landing page if OIDC is enabled and user is unauthenticated).GET /favicon.ico: Serves the favicon.POST /toggle?action=start: Start all instances. Returns 200 (no-op) if already running, 409 if transitioning.POST /toggle?action=stop: Stop all instances. Returns 200 (no-op) if already stopped, 409 if transitioning.GET /login: Initiates OIDC login flow (only when OIDC is enabled).POST /logout: Clears session and redirects to landing page (only when OIDC is enabled).GET /callback: OIDC callback endpoint (only when OIDC is enabled).
- Add error handling for AWS API calls.
River Guide is released under the MIT License. See the LICENSE file for more details.

