Guide · Self-hosting
Self-host S3, IAM and Lambda on your homelab
HomeCloud is one Go binary that serves the AWS APIs and runs the work as containers on the same Docker host: S3 on MinIO, Lambda on AWS's runtime images, IAM enforced on every call. This guide covers running it on a home server or a VPS and keeping it there.
A homelab usually ends up with MinIO for objects, something for functions, and its own idea of users and permissions. If the code you run there also targets AWS, that is three sets of client configuration and none of them the AWS SDKs'. HomeCloud puts S3, IAM, Lambda and about 30 other AWS services behind one endpoint, with one set of credentials and AWS's policy language, so aws s3 cp, boto3 and Terraform work against your own hardware. It also includes a web console, CloudWatch logs and metrics, and a CloudTrail record of every API call.
What you need
| To try it | Comfortable | |
|---|---|---|
| CPU | 2 vCPUs | 4+ vCPUs |
| Memory | 4 GB | 8–16 GB |
| Disk | 30 GB | 100 GB+ SSD |
| OS | 64-bit Linux with systemd (Ubuntu 24.04 and Debian 12 are the tested targets), amd64 or arm64, Docker Engine | |
Everything HomeCloud runs is a container on that host, so the machine's size is the size of your cloud: add up the databases, functions and instances you plan to keep running. It needs outbound internet access to pull images (MinIO, database engines, Lambda runtimes). A mini PC or an old desktop with 16 GB of memory is a good home for it.
1. Install
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER" # log out and back in
curl -fsSL https://homecloud.pages.dev/scripts/install.sh | sh
homecloud doctor # checks Docker, memory, ports
The install script downloads the latest release for your architecture, verifies its SHA-256 checksum and installs /usr/local/bin/homecloud. Run HomeCloud as this normal user, not root.
Or with the container image
The image ghcr.io/solinode/homecloud (amd64 and arm64, tags latest and one per release) runs the same server and manages the host's Docker through the mounted socket:
docker run -d --name homecloud --restart unless-stopped \
-p 127.0.0.1:8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v homecloud-data:/data \
ghcr.io/solinode/homecloud
docker logs homecloud # the root console password, shown once
2. Run it as a service
Start the server once in the foreground with the settings you want to keep. Flags are saved to config.json in the data directory and reused on every start:
homecloud serve --public-url https://cloud.example.com # copy the root password, then Ctrl-C
sudo homecloud service install --system # systemd unit, starts after docker.service
journalctl -u homecloud -f
With the image, Docker's restart policy does this job instead.
3. Reach it from other machines
The API and console listen on 127.0.0.1:8080 by default. Do not bind them to a public address without TLS: access keys and session tokens would cross the network in the clear. Pick one:
- VPS with a domain: keep HomeCloud on loopback and put Caddy in front. Caddy gets the Let's Encrypt certificate; start HomeCloud with
--public-url https://cloud.example.com --trusted-proxies 127.0.0.1/32so generated links and IAM conditions onaws:SourceIpsee the real client. - Home LAN or Tailscale: bind to the network and let HomeCloud make its own certificate.
homecloud serve --addr 0.0.0.0:8443 \
--public-host homelab.tailnet.ts.net --tls-self-signed
Docker publishes container ports around ufw, so HomeCloud keeps MinIO, its registry and its DNS server on 127.0.0.1 unless you ask otherwise. The firewall section of the server guide lists every port.
4. Use it: S3, IAM and Lambda
Keep the root key for administration and give each person or job its own IAM user:
homecloud iam create-user alice --password 'a-long-passphrase' --policy AdministratorAccess
homecloud iam create-access-key alice # the secret is shown once
homecloud iam create-user backup-job --policy AmazonS3FullAccess
homecloud iam create-access-key backup-job
# homelab-cert.pem: a copy of the server's <data-dir>/tls/cert.pem
homecloud configure --endpoint https://homelab.tailnet.ts.net:8443 --ca-file ./homelab-cert.pem
eval "$(homecloud aws-env)"
aws s3 mb s3://photos
aws s3 sync ~/Pictures/2026 s3://photos/2026/
aws s3 presign s3://photos/2026/cat.jpg --expires-in 3600
Bucket policies, versioning, lifecycle expiry and static websites work. Lambda functions run on AWS's runtime images, can be triggered by SQS queues, DynamoDB streams, EventBridge rules and schedules, or served through an HTTP API or a function URL; see testing Lambda locally for the commands. Policies support conditions, roles, permissions boundaries and the IAM policy simulator.
5. Backups and upgrades
homecloud backup streams an archive of the data directory (state, the master key, function code, logs) and every HomeCloud Docker volume: databases, S3 objects, registry images, EBS volumes. Instance root disks are not included.
# nightly at 03:00; % must be escaped in crontab. Add your own rotation.
0 3 * * * homecloud backup -o /var/backups/homecloud-$(date +\%F).tar.gz
The archive contains master.key, which decrypts secrets and KMS key material, so encrypt it and copy it off the machine. homecloud restore rebuilds the data directory and volumes on the same or a new server. With the image, run docker exec homecloud homecloud backup -o - > backup.tar.gz.
Upgrades verify the release checksum before replacing the binary, and data migrates on the next start:
homecloud upgrade --check
homecloud backup -o before-upgrade.tar.gz
sudo homecloud upgrade && sudo systemctl restart homecloud
Know the trade-offs
- HomeCloud is root on the host. It needs the Docker socket, which is root-equivalent, so HomeCloud administrators are host administrators. Containers are not a VM boundary; do not host untrusted tenants.
- One host, one region, one account. Multi-node clusters are designed, not built. S3 runs on a single MinIO, not distributed erasure coding, so keep backups.
- VM instances (Ubuntu 24.04 and Debian 12 images) want
/dev/kvm; without it they are emulated and slow. Container instances need nothing extra.
The complete walkthrough, with DNS, port 53 delegation, KVM and troubleshooting, is docs/install-server.md. A server like this is also a good base for a classroom: see teaching AWS without an AWS account.