Claude Code as Homelab Assistant - Part 3: Deploying a New Service
Claude Code as Homelab Assistant - Part 3: Deploying a New Service
Introduction
In Part 1 we set up Claude Code and performed the first security audit. In Part 2, Claude Code found and fixed a bug. In Part 3, I’m showing the third use case: deploying a completely new service from scratch - compose file, Traefik integration, HTTPS, backup extension.
The service is Wallos - an open-source subscription tracker. Self-hosted instead of storing financial data somewhere in the cloud, with multi-currency support, categories, and notifications. Exactly right for someone who wants to keep track of monthly expenses without handing them over to a third party.
What particularly interested me about this run: our setup is non-trivial.
Traefik as a reverse proxy with automatic wildcard certificate, DNS challenge via
Hostinger, proxy_net as a shared network for all services. This is the kind of
setup where you’d normally have to look up all the labels and network configurations yourself.
Claude Code took over completely - and even solved errors that came up along the way.
Main Section
The Slash Command
/deploy-service
Claude Code asks for service name and URL. The response:
I want to install Wallos at wallos.home.maker-ronin.cloud. The project and documentation can be found here: https://wallosapp.com/

What happened in the next 34 seconds:
- Visited wallosapp.com and read documentation
- Checked GitHub repo for the official compose file
- Read existing stack as reference - Manyfold, to understand Traefik labels and network configuration
- Queried Docker Hub for the current stable tag -
4.7.2instead of:latest - Created a complete deployment plan
The result was a clean plan with all details:
| Property | Value |
|---|---|
| Stack path | /home/ronin/docker/wallos/ |
| Subdomain | wallos.home.maker-ronin.cloud |
| Image | bellamy/wallos:4.7.2 |
Volumes, environment variables, ports, network - everything listed before a single file was written.
Step 2 - Creating Files
After the first “OK”, Claude Code created the files on the server.

Something interesting happened: the first attempt failed.
fish: Expected a string, but found a redirection
cat > /home/ronin/docker/wallos/docker-compose.yml << 'EOF'
The server runs Fish Shell instead of Bash - and Fish doesn’t support heredoc syntax. Claude Code recognized this immediately, without me needing to intervene:
“Fish shell - no heredoc. I’ll use
teeinstead.”
Second attempt with printf ... | tee - works. Files created, immediately
verified by re-reading.
The finished compose file:
services:
wallos:
container_name: wallos
image: bellamy/wallos:4.7.2
environment:
TZ: 'Europe/Vienna'
volumes:
- ./db:/var/www/html/db
- ./logos:/var/www/html/images/uploads/logos
restart: unless-stopped
networks:
- proxy_net
security_opt:
- no-new-privileges:true
labels:
- "traefik.enable=true"
- "traefik.http.routers.wallos.rule=Host(`wallos.home.maker-ronin.cloud`)"
- "traefik.http.routers.wallos.entrypoints=websecure"
- "traefik.http.routers.wallos.tls.certresolver=letsencrypt"
- "traefik.http.services.wallos.loadbalancer.server.port=80"
networks:
proxy_net:
external: true
Everything correct - fixed tag, both volumes, proxy_net external, all Traefik labels
complete, no-new-privileges:true as security best practice.
Step 3 - Start and Traefik Diagnostics

docker compose up -d - container starts, healthy after a few seconds.
Then the URL test: HTTP code 000 - the route wasn’t active yet. Instead of just waiting,
Claude Code investigated on its own:
- Queried Traefik API if the route was known
- Python JSON parsing failed - tried a different approach
docker network inspect proxy_net- Wallos is in the network- Queried Traefik from within - route found
"service": "wallos",
"rule": "Host(`wallos.home.maker-ronin.cloud`)",
"priority": 37
Route active. Second URL test: HTTP 302 - redirect to app. ✅
Step 4 - Backup

Claude Code read the backup script and determined: Wallos uses bind mounts, not Docker volumes. The suggested entry for the backup script:
# Wallos data
log "Backing up Wallos data..."
restic backup \
/home/ronin/docker/wallos/db \
/home/ronin/docker/wallos/logos \
--tag wallos \
--verbose
I’ll add the entry to the script manually - this keeps control over the backup script with me.
Claude Code’s summary after 1 minute 5 seconds:
| Step | Status |
|---|---|
| Image researched (bellamy/wallos:4.7.2) | ✅ |
| Stack files created | ✅ |
| Container started & healthy | ✅ |
| Traefik route active, URL responds (302) | ✅ |
| Backup extension documented | ✅ |
The Result

https://wallos.home.maker-ronin.cloud - Wallos is running, HTTPS works.
The wildcard certificate *.home.maker-ronin.cloud applies automatically to every new
subdomain - no extra ACME configuration, no separate DNS challenge for Wallos.
That’s the advantage when Traefik is set up cleanly: every new service
gets HTTPS automatically.

After creating the admin account - Wallos is running, logged in, ready for the first subscriptions.
CLAUDE.md Grows

After deployment, Claude Code itself identified two learnings and suggested
updating CLAUDE.md:
Learning 1 - Fish Shell:
The SSH session runs under Fish Shell. << 'EOF' heredoc syntax doesn’t work -
Claude Code had to switch to printf. From now on, CLAUDE.md states:
“Shell is fish - for file writes use
printforteeinstead of bash heredoc.”
Learning 2 - Traefik API:
Port 8080 is not directly accessible via localhost:8080 - only within the
Traefik container. The correct way:
docker exec traefik wget -q -O- http://localhost:8080/api/...
This is also now documented in CLAUDE.md.
This is perhaps the most subtle but important feature of this setup: the context
improves with every session. What was an unexpected error today becomes familiar territory
on the next deployment - Claude Code knows it because it’s in
CLAUDE.md.
A small mishap on the side: On the first registration attempt, I didn’t note the password
and couldn’t log in. Fix: delete the SQLite database,
restart the container, register again. rm /home/ronin/docker/wallos/db/wallos.db && docker restart wallos - done in 30 seconds. Claude Code deploys the service,
but you still need to create the admin account yourself. 😄
Conclusion
What impressed me most about this run is not that it worked - but how it handled errors. Fish Shell instead of Bash, Python JSON parsing errors, Traefik route not yet active - each time Claude Code recognized the problem, chose a different approach, and continued. No manual intervention, no explanation from me needed.
The most challenging aspect of this setup is the Traefik integration: wildcard certificate,
DNS challenge, proxy_net, the right labels in the right combination. This is exactly the kind of configuration you’d have to look up each time for a new service or copy from an existing stack. Claude Code learned from the existing stacks and transferred it correctly - in 34 seconds of planning, 1 minute 5 seconds of execution.
From idea to running service with HTTPS in under 2 minutes of active work time.
What comes next: The concept can be taken further - regular automatic health checks as a cron job, weekly audits running quietly in the background, notifications on critical findings. The foundation is there. What becomes of it depends on how far you want to take it.