Deployment guide

Homebox 0.27.0

Overview

This guide covers launching and using the Homebox 0.27.0 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. The AMI is one version of the SecureAnyCloud Helpdesk, ITSM and Project Management listing on AWS Marketplace. You select it as the software version when you subscribe and launch.

Homebox is a self-hosted inventory and organisation system for homes, home labs and small teams. You record what you own, where it is kept (nested locations such as rooms, shelves and boxes), tags, quantities, serial and model numbers, purchase and warranty details, maintenance logs, and photos or documents. You then find anything with search or by scanning a printed QR label.

Homebox is a single Go program with an embedded SQLite database, so there is no separate database server to run.

What you get:

  • HTTPS from the first boot. nginx serves Homebox on port 443 with a certificate that is generated on your instance's first boot. Port 80 redirects to HTTPS.
  • An administrator account unique to your instance, and no open sign-up. Upstream Homebox lets the first person who opens the site register and become the owner. This image instead creates the administrator itself on first boot, with a password that is generated on your instance and written to /root/homebox-credentials.txt. It also keeps public registration closed. You add people with single-use invites.
  • Fail closed. No account, password or key is baked into the image. Homebox refuses to start until first boot has written its per-instance secrets, and nginx refuses to start until first boot has finished.
  • Loopback only. Homebox listens on 127.0.0.1:7745 behind nginx. The only open ports are 22, 80 and 443.
  • Hardened defaults. Homebox runs as its own unprivileged user in a systemd sandbox. Homebox and nginx are blocked from the instance metadata service, and the AMI requires IMDSv2. Requests for a host name that the instance does not serve are dropped, and cross-site requests that change data are refused. The client address that Homebox sees (it rate-limits sign-in attempts per client) comes from the connection, never from a header that a client can forge.
  • Notifiers cannot reach your private network. Homebox notifiers send webhooks to URLs that your users enter. The image refuses notifier targets on localhost, the instance metadata service, reserved ranges and private (RFC 1918) networks such as your VPC, so a notifier cannot be used to probe private services.
  • Your data on its own volume. The database and every uploaded photo and document live on a separate 20 GiB EBS volume mounted at /data, which you can resize and snapshot on its own.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

Version: Homebox 0.27.0 is a security release. It fixes 15 advisories that affect 0.26.2. Among them are unauthenticated registration requests that could exhaust the server (registration is now rate-limited) and group members being able to take over groups that they do not own. If you run the earlier 0.26.2 version of this listing, move to this one.

What is on the image: Homebox 0.27.0 (/usr/local/bin/homebox, the official release binary, checksum verified), nginx, sqlite3, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.

Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route that you use for management).
  • A security group that allows TCP 22 (SSH), TCP 443 (the web app and API) and TCP 80 (redirects to HTTPS) from your own networks only.
1

Launch the instance

In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Select Homebox 0.27.0 on Ubuntu 24.04 as the software version, choose your Region, and select Launch through EC2.

Choose m5.large, your key pair and a security group as described above. Homebox is light, and a smaller type works for a single household. Keep the second EBS volume, because it is where your inventory, photos and documents are stored.

Alternatively, launch with the AWS CLI. Replace the values in angle brackets:

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=homebox}]'
2

Connect to your instance

Version SSH user

Homebox 0.27.0 on Ubuntu 24.04 ubuntu

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

First boot takes a few seconds. After it completes, the three units are active:

systemctl is-active homebox nginx homebox-firstboot
active active active

Homebox listens on loopback only, and nginx serves ports 80 and 443:

sudo ss -tlnp | awk 'NR==1 || /homebox|nginx|sshd/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'
State Local Peer LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:22 users:(("sshd"),("systemd")) LISTEN 127.0.0.1:7745 users:(("homebox")) LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:22 users:(("sshd"),("systemd"))
4

Get your URL and administrator password

sudo cat /root/homebox-credentials.txt

The file holds the address that Homebox is served as (your instance's public IP address by default), the administrator's email address and the password generated on this instance:

HOMEBOX_URL=https://<public-ip>/ HOMEBOX_ADMIN_EMAIL=admin@homebox.local HOMEBOX_ADMIN_PASSWORD=<24 letters and digits>

Homebox reports itself healthy, on version 0.27.0, with registration closed:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt)
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/api/v1/status" | jq '{health, allowRegistration, version: .build.version}'
{ "health": true, "allowRegistration": false, "version": "0.27.0" }
5

Sign in from your browser

Open HOMEBOX_URL in your browser. The certificate is self-signed and generated on your instance, so accept the browser warning once, or install your own certificate (Step 10). The sign-in page shows Registration Disabled, because nobody can create an account from the internet.

Sign in with the email address and password from Step 4. Then open Profile and use Change Password to set your own password.

The home page shows quick statistics, recently added items, your storage locations and tags. A new collection starts with eight example locations (Attic, Basement, Bathroom, Bedroom, Garage, Kitchen, Living Room, Office) and a few tags, which you can rename or delete:

6

Track your things

Use Create to add an item or a location. Open a location to see everything stored in it. Locations can contain other locations, such as a shelf in the garage and a box on the shelf:

Each item has details (quantity, serial and model numbers, manufacturer, insurance and purchase or warranty information, notes and an asset ID), a maintenance log, and photo or document attachments. Labels prints asset labels with QR codes, and scanning one opens the item:

7

Add people with invites

Public registration stays closed. To give someone access to your collection, open Collection, then Invites, and click + to create an invite. Each invite has a number of uses and an expiry date. Send the invite link to the person, and they register with it into your collection. An invite token that does not exist is refused, so closed registration cannot be bypassed by guessing one.

The image keeps public registration closed. A start check (/usr/local/sbin/homebox-start-guard) refuses to run Homebox if HBOX_OPTIONS_ALLOW_REGISTRATION is set to anything but false.

If you deliberately want open sign-up (for example on an isolated private network), set the option to true in /etc/homebox/homebox.env, clear the check with a systemd override, and restart. Anyone who can reach the site can then create an account, so we recommend invites instead:

sudo systemctl edit homebox
# add the two lines: [Service] and ExecStartPre=
sudo systemctl restart homebox
8

Use the REST API

Everything in the web app is available from the REST API under /api/v1. Sign in with POST /api/v1/users/login to get a token, and then send it in the Authorization header. Run these commands on the instance. The password is read from the credentials file and sent to curl on stdin, so it never appears on a command line:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt) login() {
sudo python3 -c 'import json c=dict(l.strip().split("=",1) for l in open("/root/homebox-credentials.txt") if l.startswith("HOMEBOX_ADMIN_")) print(json.dumps({"username":c["HOMEBOX_ADMIN_EMAIL"],"password":c["HOMEBOX_ADMIN_PASSWORD"],"stayLoggedIn":False}))' \
  | curl -sk --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -H 'Content-Type: application/json' \
  --data-binary @- "https://$H/api/v1/users/login" | jq -r .token; }
TOKEN=$(login) api() { printf 'header = "Authorization: %s"\n' "$TOKEN" | curl -sk -K - --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" "$@"; } api "https://$H/api/v1/users/self" | jq -r '.item | "\(.name) <\(.email)>"' api "https://$H/api/v1/groups/statistics" | jq -c '{totalUsers, totalItems, totalLocations, totalTags}'
Administrator <admin@homebox.local> {"totalUsers":1,"totalItems":0,"totalLocations":8,"totalTags":6}

Items and locations are both "entities" in Homebox (since 0.26). The following commands create an item in the Office location and find it again with a search:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt)
TOKEN=$(sudo python3 -c 'import json c=dict(l.strip().split("=",1) for l in open("/root/homebox-credentials.txt") if l.startswith("HOMEBOX_ADMIN_")) print(json.dumps({"username":c["HOMEBOX_ADMIN_EMAIL"],"password":c["HOMEBOX_ADMIN_PASSWORD"],"stayLoggedIn":False}))' \
  | curl -sk --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -H 'Content-Type: application/json' \
  --data-binary @- "https://$H/api/v1/users/login" | jq -r .token) api() { printf 'header = "Authorization: %s"\n' "$TOKEN" | curl -sk -K - --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -H 'Content-Type: application/json' "$@"; }
OFFICE=$(api "https://$H/api/v1/entities/tree" | jq -r '.[] | select(.name=="Office") | .id') api -X POST "https://$H/api/v1/entities" -d "{\"name\":\"Label printer\",\"quantity\":1,\"parentId\":\"$OFFICE\"}" | jq -r '"created: \(.name)"' api "https://$H/api/v1/entities?q=printer" | jq -r '.items[] | "\(.name) in \(.parent.name)"'
created: Label printer Label printer in Office

From your own computer, use https://<your-dns-name>/api/v1/... the same way.

For scripts, use Profile > Create API Key instead of signing in with the password. An API key has the same permissions as your account. The interactive API reference is linked as API at the bottom of every page.

9

Notifiers and private networks

Notifiers (Collection > Notifiers) post a message to a URL when something is due, for example a maintenance reminder. Because your users enter the URL, the image refuses targets inside your network. Homebox itself blocks localhost, reserved ranges and the cloud metadata address, and the image also blocks private networks (HBOX_NOTIFIER_BLOCK_LOCAL_NETS=true). A test send to each kind of target is refused before any connection is made:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt)
TOKEN=$(sudo python3 -c 'import json c=dict(l.strip().split("=",1) for l in open("/root/homebox-credentials.txt") if l.startswith("HOMEBOX_ADMIN_")) print(json.dumps({"username":c["HOMEBOX_ADMIN_EMAIL"],"password":c["HOMEBOX_ADMIN_PASSWORD"],"stayLoggedIn":False}))' \
  | curl -sk --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -H 'Content-Type: application/json' \
  --data-binary @- "https://$H/api/v1/users/login" | jq -r .token) for target in 127.0.0.1 169.254.169.254 10.0.0.5; do printf 'header = "Authorization: %s"\n' "$TOKEN" | curl -sk -K - --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" \
  -H 'Content-Type: application/json' -d "{\"url\":\"generic://$target/hook\"}" "https://$H/api/v1/notifiers/test" | jq -r --arg t "$target" '"\($t): \(.error)"' done
127.0.0.1: localhost addresses are blocked 169.254.169.254: bogon/reserved network addresses are blocked 10.0.0.5: private network addresses (RFC1918) are blocked

Public webhook services (ntfy.sh, Discord, Slack, a Gotify server with a public address, ...) work as normal. If you want a notifier to reach one service on your private network, allow just that network and restart Homebox. HBOX_NOTIFIER_ALLOW_NETS is an allowlist, so only the networks that you list are reachable:

echo 'HBOX_NOTIFIER_ALLOW_NETS=10.20.30.0/24' | sudo tee -a /etc/homebox/homebox.env
sudo systemctl restart homebox
10

Your own DNS name and certificate

Point a DNS record at the instance, and then set the name that Homebox is served as. This command creates a new self-signed certificate for the name. It updates nginx, Homebox's own base URL (used in password reset links) and the URL in /root/homebox-credentials.txt, and it keeps the name across reboots:

sudo homebox-set-hostname <your-domain>

To use a certificate from your own certificate authority instead, copy it over the generated pair and reload nginx. Running homebox-set-hostname again replaces it with a self-signed one:

sudo install -m 0644 <your-domain>.crt /etc/ssl/homebox/homebox.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/homebox/homebox.key
sudo nginx -t && sudo systemctl reload nginx
11

Security checks

Without a token, the API refuses you. Public registration is refused (and, from Homebox 0.27.0, rate-limited to 5 attempts a minute per client), and a sign-in posted from another web site is refused. A request for a host name that the instance does not serve gets no answer:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt)
curl -sk -o /dev/null -w 'unauthenticated API call: %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/api/v1/users/self"
curl -sk -w ' (HTTP %{http_code})\n' --resolve "$H:443:127.0.0.1" -H "Origin: https://$H" -H 'Content-Type: application/json' \
  -d '{"name":"someone","email":"someone@example.com","password":"Someone-123456789"}' "https://$H/api/v1/users/register"
curl -sk -o /dev/null -w 'cross-site sign-in attempt: %{http_code}\n' --resolve "$H:443:127.0.0.1" -H 'Origin: https://evil.example' \
  -H 'Content-Type: application/json' -d '{"username":"x","password":"y"}' "https://$H/api/v1/users/login"
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: evil.example' http://127.0.0.1/ || true
unauthenticated API call: 401 {"error":"user registration disabled"} (HTTP 403) cross-site sign-in attempt: 403 unknown host name: 000

The configuration keeps Homebox on loopback with registration closed. The secrets files are readable only by root and, for the configuration, the homebox service:

sudo grep -E '^HBOX_(WEB_HOST|OPTIONS_ALLOW_REGISTRATION|OPTIONS_TRUST_PROXY|OPTIONS_HOSTNAME|NOTIFIER_BLOCK_LOCAL_NETS)=' /etc/homebox/homebox.env
sudo stat -c '%a %U:%G %n' /etc/homebox/homebox.env /root/homebox-credentials.txt /etc/ssl/homebox/homebox.key
HBOX_WEB_HOST=127.0.0.1 HBOX_OPTIONS_ALLOW_REGISTRATION=false HBOX_OPTIONS_TRUST_PROXY=true HBOX_NOTIFIER_BLOCK_LOCAL_NETS=true HBOX_OPTIONS_HOSTNAME=https://<public-ip> 640 root:homebox /etc/homebox/homebox.env 600 root:root /root/homebox-credentials.txt 600 root:root /etc/ssl/homebox/homebox.key

Homebox runs unprivileged in a sandbox, and neither Homebox nor nginx can reach the instance metadata service. nginx passes Homebox the real client address from the connection. Homebox trusts these headers only because nginx on the same machine is the only thing that can reach it:

systemctl show homebox -p User -p ProtectSystem -p NoNewPrivileges -p IPAddressDeny
systemctl show nginx -p IPAddressDeny grep -E 'proxy_set_header (X-Forwarded-For|X-Real-IP|X-Forwarded-Host)' /etc/nginx/sites-available/sac-homebox
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 User=homebox ProtectSystem=full NoNewPrivileges=yes IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Host "";

The certificate was generated on this instance and names its own addresses:

H=$(sudo sed -nE 's#^HOMEBOX_URL=https://([^/]+)/.*#\1#p' /root/homebox-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = <public-ip>, O = sac X509v3 Subject Alternative Name: IP Address:<public-ip>, DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost
12

Data, backups and configuration

The database (homebox.db) and the uploaded photos and documents (data/) live on the separate EBS volume, bind-mounted at /var/lib/homebox:

findmnt -no SOURCE,TARGET /data
findmnt -no SOURCE,TARGET /var/lib/homebox
sudo ls /var/lib/homebox
/dev/nvme1n1 /data /dev/nvme1n1[/homebox] /var/lib/homebox data homebox.db homebox.db-shm homebox.db-wal

To back up, snapshot the /data volume. Collection > Tools in the web app also exports your inventory to CSV (Import/Export) and generates a bill of materials or printable asset ID labels. To grow the volume, resize it in EC2, and then run sudo resize2fs on its device.

Homebox reads /etc/homebox/homebox.env. The image sets the following values:

Setting Meaning Image default

HBOX_WEB_HOST / HBOX_WEB_PORT Bind address and port 127.0.0.1 / 7745 (nginx fronts it)

HBOX_OPTIONS_ALLOW_REGISTRATION Public sign-up false (invites still work)

HBOX_OPTIONS_HOSTNAME Base URL used in password reset links https://<your host> from first boot

HBOX_OPTIONS_TRUST_PROXY Take the client address from nginx true

HBOX_OPTIONS_GITHUB_RELEASE_CHECK Ask GitHub for newer releases false

HBOX_NOTIFIER_BLOCK_LOCAL_NETS Refuse notifier targets on private (RFC 1918) networks true (localhost, reserved and metadata targets are always refused)

HBOX_NOTIFIER_ALLOW_NETS Networks notifiers may reach (an allowlist) not set

HBOX_AUTH_API_KEY_PEPPER Secret mixed into stored API key hashes generated on first boot; do not change it, or existing API keys stop working

After you change a setting, run sudo systemctl restart homebox. To send password reset emails, add the SMTP settings from the Homebox documentation (HBOX_MAILER_*).

To upgrade Homebox, download the release from the Homebox project, check its checksum, replace /usr/local/bin/homebox and restart the service. Snapshot the data volume before you upgrade, because Homebox migrates the database on start.

13

Server components

Component Path

Homebox binary /usr/local/bin/homebox

Database and uploads /var/lib/homebox (on the /data volume)

Configuration /etc/homebox/homebox.env (root:homebox, 0640)

Service unit /etc/systemd/system/homebox.service

nginx site /etc/nginx/sites-available/sac-homebox

Certificate and key /etc/ssl/homebox/

First boot script /usr/local/sbin/homebox-firstboot.sh

Host name helper /usr/local/sbin/homebox-set-hostname

Credentials /root/homebox-credentials.txt (mode 0600)

Licence /usr/share/doc/homebox/LICENSE

14

Security recommendations

  • Allow ports 22, 80 and 443 in the security group from your own networks only.
  • Change the administrator password after your first sign-in, and keep /root/homebox-credentials.txt secret. If you prefer, delete the file once you have changed the password.
  • Keep public registration closed and add people with single-use invites that expire.
  • Use your own DNS name and a certificate that your clients trust (Step 10).
  • Keep the operating system patched. Unattended security upgrades are on, and sudo apt-get update && sudo apt-get upgrade applies everything else.
  • Snapshot the /data volume regularly to back up your inventory.

Support and licensing

Homebox is open source under the GNU Affero General Public License v3.0 (a copy is at /usr/share/doc/homebox/LICENSE), and there is no per-user or per-CPU licence fee. The AMI price covers SecureAnyCloud's hardening, first boot setup and support.

  • Email: sales@secureanycloud.com
  • Website: https://secureanycloud.com
  • Support: 24/7, with a 24 hour response SLA

Deploy on AWS

Launch Homebox 0.27.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS