Home server Docker Compose stack
- Custom Caddy image with duckdns DNS provider plugin for automatic TLS - ha-padriano.duckdns.org → Home Assistant, git-padriano.duckdns.org → Forgejo - Move homeassistant and forgejo onto internal bridge network - Update README to reflect HTTPS setup, new URLs, and setup steps Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|---|---|---|
| caddy | ||
| plans | ||
| samba | ||
| timemachine | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| README.md | ||
Docker Compose — Home Server
Services
| Container | Image | Purpose |
|---|---|---|
duckdns |
lscr.io/linuxserver/duckdns |
Dynamic DNS — keeps *.duckdns.org pointed at the home IP |
caddy |
caddy (custom build) |
HTTPS reverse proxy with automatic Let's Encrypt certificates via DuckDNS DNS-01 |
homeassistant |
homeassistant/home-assistant |
Home automation, reachable at https://ha-padriano.duckdns.org |
timemachine |
mbentley/timemachine:smb |
Time Machine backup server over SMB |
samba |
dperson/samba |
General SMB file share for Mac and Linux clients |
forgejo |
codeberg.org/forgejo/forgejo |
Self-hosted Git server at https://git-padriano.duckdns.org, SSH at :2222 |
Initial Setup
-
Copy and fill in the environment file:
cp .env.example .env nano .env -
Register the required DuckDNS subdomains at duckdns.org:
ha-padriano,padrianoha,padriano,git-padriano. -
Create the required host directories if they don't exist:
mkdir -p /home/padriano/projects/forgejo mkdir -p /home/padriano/shareThe Samba container runs as UID/GID 1001 internally, so the share directory must be owned by that user:
sudo chown 1001:1001 /home/padriano/share -
Add the reverse proxy trusted header config to Home Assistant:
sudo tee -a /home/padriano/projects/ha/config/configuration.yaml > /dev/null << 'EOF' http: use_x_forwarded_for: true trusted_proxies: - 172.16.0.0/12 EOF -
Bring the full stack up (first run builds the custom Caddy image):
cd /home/padriano/projects/composer docker compose up -d --build
Common Docker Compose Commands
Stack management
# Start all services (detached)
docker compose up -d
# Stop all services (containers remain)
docker compose stop
# Stop and remove all containers (data volumes are preserved)
docker compose down
# Restart all services
docker compose restart
# Restart a single service
docker compose restart homeassistant
Viewing status and logs
# Show running containers and their status
docker compose ps
# Follow logs for all services
docker compose logs -f
# Follow logs for a single service
docker compose logs -f forgejo
# Show last 50 lines for a service
docker compose logs --tail=50 timemachine
Updating images
# Pull latest images for all services
docker compose pull
# Pull for a single service
docker compose pull forgejo
# Recreate containers that have a newer image
docker compose up -d --pull always
# Recreate a single service after pulling
docker compose up -d --force-recreate forgejo
Inspecting containers
# Open a shell inside a running container
docker exec -it homeassistant bash
docker exec -it forgejo sh # alpine-based, use sh not bash
# Show resource usage (CPU, RAM, network)
docker stats
# Inspect container configuration
docker inspect forgejo
Service Notes
duckdns
- Config stored at
/home/padriano/projects/duckdns/config - Domains managed:
ha-padriano,padrianoha,padriano,git-padriano(all.duckdns.org) - Subdomains must be registered manually at duckdns.org before they can be updated
caddy
- Custom image built from
caddy/Dockerfile— adds the DuckDNS DNS provider plugin to the official Caddy image - Config at
caddy/Caddyfile; TLS certificates stored in thecaddy_dataDocker volume - Obtains free Let's Encrypt certificates via DNS-01 challenge (no extra ports needed, no cost)
- Listens on
:80(redirects to HTTPS) and:443 - Routes:
ha-padriano.duckdns.org→ Home Assistant:8123git-padriano.duckdns.org→ Forgejo:3000
- To reload config without restarting:
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
homeassistant
- Config stored at
/home/padriano/projects/ha/config - Web UI:
https://ha-padriano.duckdns.org(via Caddy) orhttp://server:8123on the LAN - Runs on the
internalbridge network so Caddy can reach it by container name configuration.yamlmust includehttp.use_x_forwarded_for: trueandtrusted_proxiesfor the Docker bridge range so HA accepts forwarded headers from Caddy- Has a healthcheck — status shows
(health: starting)for ~60s on first boot
timemachine
- Backup data stored at
/home/padriano/backup/timemachine - Uses
network_mode: hostand a fixedhostname: timemachine— the stable hostname prevents macOS from losing the backup destination after container restarts - On your Mac: System Settings → General → Time Machine → Add Backup Disk
samba
- Shared directory on the host:
/home/padriano/share— must be owned by1001:1001(the UID/GID the container uses internally); without this, the share mounts on the Mac but files cannot be written - Uses a macvlan network with static IP
192.168.1.247— avoids port 445 conflict with thetimemachinecontainer - Config stored at
samba/smb.conf; the[Share]section is the only exported share - Avahi service file at
samba/avahi-smb.serviceadvertises the share for Finder sidebar discovery (installed to/etc/avahi/services/samba.serviceon the host) - Connecting from a Mac: open Finder → Go → Connect to Server →
smb://192.168.1.247/Share - Connecting from Linux:
smbclient //192.168.1.247/Share -U sambaor mount withmount -t cifs //192.168.1.247/Share /mnt/share -o username=samba - Username and password are set via
SAMBA_USERNAME/SAMBA_PASSWORDin.env
forgejo
- All data (repos, config, SQLite DB) stored at
/home/padriano/projects/forgejo - Backing up this single directory is sufficient for a full restore
- Port 3000 is no longer exposed on the host — access is via Caddy only
First-run setup
Visit http://server:3000 on first start (LAN only) and complete the install wizard:
- Base URL:
https://git-padriano.duckdns.org - SSH domain:
git-padriano.duckdns.org - SSH port:
2222
Access
| Method | Local network | External (via DuckDNS) |
|---|---|---|
| Web UI | http://server:3000 |
https://git-padriano.duckdns.org |
| Git SSH | ssh://git@server:2222 |
ssh://git@git-padriano.duckdns.org:2222 |
For external access, forward these ports on your router to the server IP:
- TCP
443→ Caddy (HTTPS — serves both HA and Forgejo) - TCP
2222→ Forgejo SSH
Git remote URL examples
# Add remote via HTTPS
git remote add origin https://git-padriano.duckdns.org/padriano/my-repo.git
# Add remote via SSH
git remote add origin ssh://git@git-padriano.duckdns.org:2222/padriano/my-repo.git
# Clone via SSH (local)
git clone ssh://git@server:2222/padriano/my-repo.git
Disk Space
# Free space on the main filesystem
df -h /
# Free space on all mounted filesystems
df -h
# Space used by each service's data directory
du -sh /home/padriano/projects/* /home/padriano/backup/*
Data & Backup Summary
| Service | Host path | Notes |
|---|---|---|
duckdns |
/home/padriano/projects/duckdns/config |
Token cache, not critical |
caddy |
Docker volume caddy_data |
Issued TLS certificates — auto-reissued if lost |
homeassistant |
/home/padriano/projects/ha/config |
All HA config and automations |
timemachine |
/home/padriano/backup/timemachine |
Mac backup sparsebundles |
samba |
/home/padriano/share |
General file share — back up as needed |
forgejo |
/home/padriano/projects/forgejo |
All repos, DB, config |