Applications AWS

Homebox 0.26.2 on AWS User Guide

| Product: Homebox 0.26.2 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the Homebox 0.26.2 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg Helpdesk, ITSM and Project Management listing on AWS Marketplace; you pick 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, then find anything with search or by scanning a printed QR label. It is a single Go program with an embedded SQLite database, so there is no separate database server to run.

The cloudimg image adds:

  • HTTPS from the first boot. nginx serves Homebox on port 443 with a certificate 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 generated on your instance and written to /root/homebox-credentials.txt, and 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; the AMI requires IMDSv2; requests for a host name the instance does not serve are dropped; cross site requests that change data are refused; and the client address Homebox sees (it rate limits sign-in attempts per client) comes from the connection, never from a header a client can forge.
  • 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.

What is on the image: Homebox 0.26.2 (/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 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.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Homebox 0.26.2 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (Homebox is light; a smaller type works for a single household), your key pair and a security group as above. Keep the second EBS volume: it is where your inventory, photos and documents are stored.

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}]'

Step 2: Connect to your instance

Version SSH user
Homebox 0.26.2 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot takes a few seconds. Then the three units are active:

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

Homebox listens on loopback only; 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"))

Step 4: Get your URL and administrator password

sudo cat /root/homebox-credentials.txt

The file holds the address 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.26.2, 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.26.2"
}

Step 5: Sign in from your browser

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

The Homebox sign-in page with Email and Password fields, a Login button and the note Registration Disabled below the form

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:

The Homebox home page: quick statistics for total value, items, locations and tags, a Recently Added table with five items, and the storage locations Attic, Basement, Bathroom, Bedroom, Garage, Kitchen, Living Room and Office

Step 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 (a shelf in the garage, a box on the shelf):

The Office location page listing three items as cards: a 27 inch monitor, a home server and a laptop, each with its quantity and tags

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; scanning one opens the item:

The Home server item page: its path Office, the tags Electronics and Servers, and the Details panel with quantity, serial number, model number, manufacturer, insured, archived, notes and asset ID

Step 7: Add people with invites

Public registration stays closed. To give someone access to your collection, open Collection, then Invites, and press + 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 Manage Collection page on the Invites tab, with the Members, Invites, Notifiers, Settings, Entity Types and Tools tabs and a plus button to create an invite

The image keeps public registration closed, and 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 it 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

Step 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, then send it in the Authorization header. 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 0.26. This creates an item in the Office location and finds 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.

Step 9: Your own DNS name and certificate

Point a DNS record at the instance, then set the name Homebox is served as. This mints a new self signed certificate for the name, updates nginx, Homebox's own base URL (used in password reset links) and the URL in /root/homebox-credentials.txt, and 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

Step 10: Security checks

Without a token the API refuses you, public registration is refused, a sign-in posted from another web site is refused, and a request for a host name 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, and the secrets files are readable by root (and, for the configuration, the homebox service) only:

sudo grep -E '^HBOX_(WEB_HOST|OPTIONS_ALLOW_REGISTRATION|OPTIONS_TRUST_PROXY|OPTIONS_HOSTNAME)=' /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_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, neither Homebox nor nginx can reach the instance metadata service, and 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/cloudimg-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 = cloudimg
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

Step 11: 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, then run sudo resize2fs on its device.

Homebox reads /etc/homebox/homebox.env; the image sets:

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_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 changing 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 do; Homebox migrates the database on start.

Step 12: 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/cloudimg-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

Step 13: 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 (delete it once you have changed the password, if you prefer).
  • Keep public registration closed and add people with single use invites that expire.
  • Use your own DNS name and a certificate your clients trust (Step 9).
  • 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); there is no per user or per CPU licence fee. The AMI price covers cloudimg's hardening, first boot setup and support.

  • Email: support@cloudimg.co.uk
  • Website: https://www.cloudimg.co.uk
  • Support: 24/7, with a 24 hour response SLA