Deployment guide

Homebox 0.26.2

Overview

This guide covers launching and using the Homebox 0.26.2 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud 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 and where it is kept, using nested locations such as rooms, shelves and boxes. You can also record 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.

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 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 creates the administrator itself on first boot instead. The password is generated on your instance and written to /root/homebox-credentials.txt, and public registration stays 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 the instance does not serve are dropped, and cross-site requests that change data are refused. Homebox rate limits sign-in attempts per client, and the client address it sees 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. You can resize and snapshot it on its own.
  • A fully patched base. Ubuntu 24.04 LTS is fully patched at build time, with unattended security upgrades switched on.
  • Software 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.

The default SSH user is ubuntu. The architecture is x86_64, and the recommended instance type is m5.large.

Prerequisites

  • An AWS account subscribed to the listing.
  • An EC2 key pair.
  • 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.
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 select your Region. Then choose Launch through EC2.

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

To launch with the AWS CLI instead, 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

Connect over SSH with your key pair. For Homebox 0.26.2 on Ubuntu 24.04, the SSH user is ubuntu.

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

Check the services

First boot takes a few seconds. After it finishes, 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"))
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 that it is 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" }
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 9). The sign-in page shows Registration Disabled, so 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. You can rename or delete them:

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. Use Labels to print asset labels with QR codes. Scanning a label opens the item:

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 nobody can bypass closed registration 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 it to true in /etc/homebox/homebox.env. Then 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, then send it in the Authorization header.

Run the following 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. 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

Use your own DNS name and certificate

Point a DNS record at the instance, then set the name Homebox is served as. This command mints 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. The name persists 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 certificate:

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
10

Security checks

Run these checks to confirm the lockdown. Without a token the API refuses you. Public registration is refused, and so is a sign-in posted from another web site. 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. Only root can read the secrets files, and for the configuration file the homebox service can read it too:

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, 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 is 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
11

Data, backups and configuration

The database (homebox.db) and the uploaded photos and documents (data/) live on the separate EBS volume, which is 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. In the web app, Collection > Tools 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 these values:

  • HBOX_WEB_HOST / HBOX_WEB_PORT: the bind address and port. Image default: 127.0.0.1 / 7745 (nginx fronts it).
  • HBOX_OPTIONS_ALLOW_REGISTRATION: public sign-up. Image default: false (invites still work).
  • HBOX_OPTIONS_HOSTNAME: the base URL used in password reset links. Image default: https://<your host> from first boot.
  • HBOX_OPTIONS_TRUST_PROXY: takes the client address from nginx. Image default: true.
  • HBOX_OPTIONS_GITHUB_RELEASE_CHECK: asks GitHub for newer releases. Image default: false.
  • HBOX_AUTH_API_KEY_PEPPER: a secret mixed into stored API key hashes. It is 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 first, because Homebox migrates the database on start.

12

Server components

  • 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
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. 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 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 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.26.2 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