Gorse
Overview
Gorse is an open-source recommender system engine written in Go. You feed it users, items and feedback such as clicks, stars or purchases through a REST API, and it returns personalized recommendations for each user. It also provides item-to-item and user-to-user neighbours, session-based recommendations, and popular or latest non-personalized lists as a fallback. A built-in web dashboard lets you inspect your data, review recommendations and watch the background training tasks.
This SecureAnyCloud image installs the official all-in-one gorse-in-one engine at /usr/local/bin/gorse-in-one, running as the gorse service bound to loopback 127.0.0.1:8088, behind nginx on port 80. The engine serves both the RESTful recommendation API (under /api/) and the web dashboard on the same port. It is backed by an embedded SQLite data and cache store on the OS disk, so there is no external database or cache to provision. nginx is ready for your TLS certificate.
Secure by default, with no default login. Gorse ships with an empty API key and empty dashboard credentials, which leaves both the REST API and the dashboard open. This image never ships that way.
A gorse-firstboot.service oneshot generates a unique API key, dashboard password and admin key on each VM's first boot and writes them to a root-only file. The engine is marked ready to start only once those secrets are in place, so every API request requires your key and the dashboard requires your login from the very first request. No two VMs share a secret, and none is baked usable into the image.
Always current. On first boot, the appliance downloads the newest Gorse release, falling back to the baked version if the network is unavailable. Every launch therefore runs current software rather than the version frozen at build time.
What you get:
- Gorse (verified at 0.5.11) as the official all-in-one
gorse-in-oneengine gorse.servicebound to loopback127.0.0.1:8088, serving the REST API and dashboard- An embedded SQLite data and cache store on the OS disk, with no external database or cache
- An nginx reverse proxy on port 80, ready for TLS
gorse-firstboot.servicefor the first-boot secrets, binary refresh and info note- A unique per-VM API key, dashboard password and admin key generated on first boot, in a root-only
0600file - An Ubuntu 24.04 LTS base, patched at build time
- 24/7 SecureAnyCloud support, 24h response SLA
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet.
Gorse is a lightweight, CPU-only engine with no GPU requirement. The recommended VM size is Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and small catalogues. For production workloads with bigger datasets, use Standard_D2s_v5 or larger.
Gorse keeps its store on the OS disk, so expand the disk before loading large catalogues.
Deploy from the Azure Portal
Search the Marketplace for Gorse on Ubuntu 24.04 and choose your VM size.
Attach a network security group (NSG) that allows TCP 22 (SSH) from your management network. Also allow TCP 80 and 443 (the API and dashboard) from the networks and applications that need to reach it.
In production, front port 80 with TLS (see Step 8).
Deploy from the Azure CLI
RG="gorse-prod"; LOCATION="eastus"; VM_NAME="gorse-01" IMAGE_URN="sac1647283583153:gorse-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name gorse-vnet --address-prefix 10.90.0.0/16 --subnet-name gorse-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name gorse-nsg az network nsg rule create -g "$RG" --nsg-name gorse-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name gorse-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:gorse-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name gorse-vnet --subnet gorse-subnet --nsg gorse-nsg --public-ip-sku StandardConnect via SSH
ssh azureuser@<vm-ip>Verify the services are running
Gorse listens on loopback 127.0.0.1:8088, and nginx fronts it on port 80. The health endpoint is public, and every other API endpoint requires your key.
sudo systemctl start gorse nginx 2>/dev/null || true
sudo systemctl is-active gorse nginx ss -tln | grep -E ':80 |127.0.0.1:8088' echo "health -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/api/health/ready)"You should see both services active, the listening sockets, and HTTP 200 from the health endpoint.
Read your per-VM secrets
Your API key, dashboard password and admin key were generated on this VM's first boot and stored in a root-only file. Read them and keep them secret. Then confirm that the REST API rejects an unauthenticated request and accepts your key.
sudo ls -l /root/gorse-info.txt echo "no key -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/api/users)"
KEY=$(sudo grep '^GORSE_API_KEY=' /root/gorse-info.txt | cut -d= -f2-)
echo "with key -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -H "X-API-Key: $KEY" http://127.0.0.1/api/users)"The info note is owned root:root with mode 0600.
An unauthenticated call to /api/users returns 401. The same call with your X-API-Key header returns 200, because the engine enforces the key on every /api/* endpoint except the public health checks.
Feed data and get recommendations via the REST API
Load your API key into a shell variable, then send Gorse a few users, items and feedback events. Items carry categories and a timestamp. Feedback records that a user starred an item.
Gorse serves the latest items straight from the store. It returns per-user recommendations, falling back to the latest items until the collaborative filtering model has trained on your feedback.
KEY=$(sudo grep '^GORSE_API_KEY=' /root/gorse-info.txt | cut -d= -f2-) H1="X-API-Key: $KEY"; H2="Content-Type: application/json";
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
curl -s -X POST http://127.0.0.1/api/users -H "$H1" -H "$H2" \
--data '[{"UserId":"alice","Labels":{}},{"UserId":"bob","Labels":{}}]' >/dev/null
curl -s -X POST http://127.0.0.1/api/items -H "$H1" -H "$H2" --data "[ {\"ItemId\":\"movie_inception\",\"Categories\":[\"scifi\"],\"Timestamp\":\"$TS\",\"Labels\":{}}, {\"ItemId\":\"movie_matrix\",\"Categories\":[\"scifi\"],\"Timestamp\":\"$TS\",\"Labels\":{}}, {\"ItemId\":\"movie_coco\",\"Categories\":[\"animation\"],\"Timestamp\":\"$TS\",\"Labels\":{}}]" >/dev/null
curl -s -X POST http://127.0.0.1/api/feedback -H "$H1" -H "$H2" --data "[ {\"FeedbackType\":\"star\",\"UserId\":\"alice\",\"ItemId\":\"movie_inception\",\"Timestamp\":\"$TS\"}, {\"FeedbackType\":\"star\",\"UserId\":\"alice\",\"ItemId\":\"movie_matrix\",\"Timestamp\":\"$TS\"}, {\"FeedbackType\":\"star\",\"UserId\":\"bob\",\"ItemId\":\"movie_inception\",\"Timestamp\":\"$TS\"}]" >/dev/null echo "latest items: $(curl -s -H "$H1" 'http://127.0.0.1/api/latest?n=5' | jq -r '[.[].Id] | join(", ")')" echo "recommend for alice: $(curl -s -H "$H1" 'http://127.0.0.1/api/recommend/alice?n=5' | jq -r 'join(", ")')"GET /api/latest returns the items you just inserted, and GET /api/recommend/alice returns a non-empty list of recommended item IDs.
As more feedback accumulates, Gorse's background tasks train the collaborative filtering model. The personalized recommendations then become tailored to each user's history.
Open the web dashboard
Gorse ships a web dashboard for inspecting your data, recommendations and background tasks. It is served on the same port as the API and is protected by the per-VM dashboard login. Confirm that it is reachable and requires authentication.
echo "login page -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/login)"
echo "dashboard -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"The login page returns 200. A request to the dashboard root returns 302, which redirects an unauthenticated visitor to the login form.
In a browser, open http://<vm-ip>/ and sign in as admin with the GORSE_DASHBOARD_PASSWORD value from /root/gorse-info.txt.
Once you are signed in, the Overview page summarizes how many users, items and feedback events the recommender knows about, with recommendation performance over time.
The Items page lists the catalogue the recommender serves, with each item's categories, timestamp and labels.
The Users page lists the users known to the recommender. Each row links through to that user's personalized recommendations.
Enable HTTPS
nginx fronts the API and dashboard on port 80 and is ready for TLS. Point a DNS record at the VM, then obtain a certificate with certbot and let certbot configure nginx for port 443.
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comAfter the certificate is issued, restrict the NSG so that only 443 (and 22 from your management network) is reachable. Then use the API and dashboard over https://your-domain.example.com/.
Persistence, first boot and updates
The recommender's data and cache live in embedded SQLite databases on the OS disk under /var/lib/gorse/. They are captured into the image, so a VM launched from this image is ready immediately.
The first-boot service generates the per-VM secrets, refreshes the Gorse binary to the latest release and marks the engine ready. It then disables itself, so subsequent reboots are unaffected. The OS is patched at build time and ships with unattended security upgrades enabled.
Support
Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.
This is a repackaged open-source software product, with additional charges for SecureAnyCloud support services. Gorse is licensed under the Apache License 2.0 and is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch Gorse on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This guide covers deploying and operating Gorse on AWS using SecureAnyCloud's pre-configured Amazon Machine Image. Gorse is an open-source recommender system engine written in Go. You feed it users, items and feedback through a clean REST API, and it returns personalized recommendations, with popular and latest non-personalized fallbacks, all served from a single self-contained process.
The image installs Gorse as the official single all-in-one gorse-in-one binary (master, server and worker in one process). It is backed by an embedded SQLite data and cache store on the instance disk, so there is no Redis and no separate database to run. The engine is a CPU-only engine with no GPU requirement.
The engine binds loopback only (127.0.0.1:8088). nginx is the sole network-facing surface, reverse proxying HTTP on port 80 and ready for you to add your TLS certificate.
Secure by default. Gorse ships upstream with an empty API key and empty dashboard credentials, which leaves both the REST API and the admin dashboard wide open. This image never boots in that state.
What you get:
- A unique API key, dashboard password and admin key, generated on each instance's first boot and written to a root-only file
- An engine that starts only after those secrets are in place
- No shared or default credentials, and nothing usable baked into the image
- A first-boot refresh to the newest Gorse release, so every launch runs current software
The recommended security group for this listing opens port 22 (SSH) and port 80 (HTTP) only. Restrict both to your own trusted network, and place TLS in front of the engine before exposing it to the public internet.
Connecting to your instance
Connect over SSH as the default login user for your operating system variant, using the EC2 key pair you selected at launch.
For the Ubuntu 24.04 LTS variant, the login user is ubuntu. For example, run ssh -i your-key.pem ubuntu@<instance-public-ip>.
Reach the web dashboard over HTTP at http://<instance-public-ip>/ and the REST API at http://<instance-public-ip>/api/.
Prerequisites
- An AWS account with permission to launch EC2 instances and subscribe to AWS Marketplace products
- An EC2 key pair for administrative SSH access
- A security group that allows inbound TCP
80(HTTP) from the networks that should reach the service, and22(SSH) from your management network only - An instance type of m5.large or larger (recommended)
Launch from AWS Marketplace
- Find the Gorse listing in AWS Marketplace. Choose Continue to Subscribe, then Continue to Configuration, then Continue to Launch.
- Select the Ubuntu 24.04 delivery option, your Region, an instance type (m5.large or larger) and your EC2 key pair.
- For the security group, allow inbound
80from your users and restrict22to your management network. - Launch the instance. When it is running, browse to
http://<instance-public-ip>/.
Launch from the AWS CLI
Launch the image from the command line, restricting access with a security group of your own. Replace the example AMI ID, key name and security group ID with your own values before you run the command:
aws ec2 run-instances \
--image-id <ami-id-from-listing> \
--instance-type m5.large \
--key-name my-key \
--security-group-ids sg-yourgroup \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=gorse}]'
# when the instance is running, browse to http://<public-ip>/Retrieve your per-instance secrets
Gorse's REST API requires an API key, and the dashboard requires a login. Both, plus an admin key and the resolved URLs, are generated uniquely on this instance's first boot and written to a root-only file. Retrieve them over SSH:
sudo cat /root/gorse-info.txtThe file lists the values your applications and operators need. Secrets are redacted in this example:
GORSE_API_KEY=<redacted> GORSE_ADMIN_API_KEY=<redacted> GORSE_DASHBOARD_USER=admin GORSE_DASHBOARD_PASSWORD=<redacted> GORSE_URL=http://<instance-public-ip>/ GORSE_API_URL=http://<instance-public-ip>/api/Keep this file secret. No two instances share these values, and none is baked into the image.
Sign in to the dashboard
Browse to http://<instance-public-ip>/. Gorse redirects you to the dashboard login.
Sign in with the username admin and the GORSE_DASHBOARD_PASSWORD from your info file. The Overview opens, with live counts of users, items and feedback, a recommendation performance chart, and non-personalized recommendation lists.
Verify the deployment
Over SSH on the instance, confirm that the services are up, the engine is the expected version, the health endpoint is ready, and the API key is enforced.
Both services are active:
systemctl is-active gorse.service nginx.serviceactive activeThe engine is the pinned Gorse release. Each instance also updates itself to the newest release on first boot:
/usr/local/bin/gorse-in-one --versionVersion: 0.5.11 API version: v0.2.7 Go version: go1.26.4 OS/Arch: linux/amd64The health endpoint reports the data and cache stores connected:
curl -s http://127.0.0.1/api/health/ready{ "Ready": true, "DataStoreConnected": true, "CacheStoreConnected": true }The REST API rejects an unauthenticated request (401) and accepts your per-instance key. The following calls read the latest items back. Substitute the GORSE_API_KEY from your info file for <your-api-key>:
curl -s -o /dev/null -w 'unauthenticated: %{http_code}\n' http://127.0.0.1/api/latest
curl -s -H "X-API-Key: <your-api-key>" "http://127.0.0.1/api/latest?n=5"unauthenticated: 401 [{"Id":"demo_item_5","Score":...},{"Id":"demo_item_4","Score":...}, ... ]On a freshly launched instance, the datastore is empty until you insert your own data (Step 7).
Browse your data in the dashboard
Use the dashboard's Items, Users and Advance views to browse and search the data you have loaded, inspect individual records, and review recommendations.
Use the REST API from your application
Your application talks to Gorse over the REST API, passing your key in the X-API-Key header. Insert users, items and feedback, then request recommendations.
Replace YOUR_API_KEY with your GORSE_API_KEY and <instance-public-ip> with your instance address:
# insert an item curl -s -X POST "http://<public-ip>/api/items" \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '[{"ItemId":"item_42","IsHidden":false,"Categories":["news"],"Timestamp":"2026-07-24T00:00:00Z","Labels":{},"Comment":"example"}]'
# record positive feedback from a user curl -s -X POST "http://<public-ip>/api/feedback" \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '[{"FeedbackType":"star","UserId":"user_1","ItemId":"item_42","Timestamp":"2026-07-24T00:00:00Z","Value":1}]'
# get recommendations for a user curl -s -H "X-API-Key: YOUR_API_KEY" "http://<public-ip>/api/recommend/user_1?n=10"Gorse serves collaborative filtering and content-aware recommendations, item-to-item and user-to-user neighbors, session-based recommendations, and latest and popular non-personalized lists.
Personalized results appear once the background training tasks have run over your data.
Monitor background training tasks
The Tasks view shows Gorse's background jobs, with their status, timing and progress. The jobs include loading the dataset, generating recommendations and cache maintenance.
Enable TLS for production
nginx fronts the engine on port 80 and is ready for your certificate. For a production deployment, point a domain name at the instance and add a CA-signed certificate, for example with the ACME client of your choice:
# point http://<your-domain> at this instance first, then obtain a certificate
sudo certbot --nginx -d <your-domain>After you enable TLS, update your security group to allow 443 and redirect 80 to HTTPS. Then update the URLs your applications use.
Security notes
- The API key, dashboard password and admin key are generated per instance on first boot and stored only in
/root/gorse-info.txt(mode0600, owned by root). Rotate them by regenerating the values in/etc/gorse/config.tomland restartinggorse.service. - Gorse binds loopback only (
127.0.0.1:8088), and nginx on port 80 is the sole network-facing surface. Keep the security group restricted to the networks that need access, and place TLS in front before you expose the service publicly. - The image ships with no data and no usable credential. The engine will not start until first boot has written per-instance secrets.
- Keep the instance patched. The dashboard footer links to the Gorse documentation and API reference.
Support
SecureAnyCloud provides 24/7 technical support for this product by email and live chat. Our engineers help with deployment, securing the API, enabling a real domain and CA-signed certificate, integrating your application through the REST API and client libraries, and recommender tuning.
- Email: sales@secureanycloud.com
- Live chat: available 24/7
Deploy on AWS
Launch Gorse on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com