orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1name: orchard-search
2
3# One service. The model lives behind llm.bythewood.me now, so this site holds
4# no weights and asks for no GPU, and the key in .env is what lets it through
5# that gateway. Two services here meant a second copy of the weights on an 8GB
6# card, so whichever of search and chat you used last evicted the other.
7#
8# No published ports. Caddy reaches the app by container name on orchard-edge.
9
10services:
11 app:
12 build:
13 context: .
14 dockerfile: Dockerfile
15 container_name: orchard-search
16 restart: unless-stopped
17 # Longer than Docker's 10s default so an answer in flight finishes and the
18 # database closes cleanly rather than being killed mid-write.
19 stop_grace_period: 30s
20 environment:
21 LLM_URL: http://orchard-llm:8000
22 LLM_KEY: ${LLM_KEY:?create a key at llm.bythewood.me and put it in .env}
23 volumes:
24 - data:/data
25 # Roomier than the static sites: this one holds a page archive with a full
26 # text index and parses HTML on the request path. Still a ceiling to fail
27 # against rather than a target, since this machine is also a workstation.
28 deploy:
29 resources:
30 limits:
31 cpus: "1.00"
32 memory: 512M
33 healthcheck:
34 test: ["CMD", "/app", "-healthcheck"]
35 interval: 30s
36 timeout: 5s
37 retries: 3
38 start_period: 10s
39 security_opt:
40 - no-new-privileges:true
41 logging:
42 driver: json-file
43 options:
44 max-size: "10m"
45 max-file: "3"
46 networks: [edge]
47
48volumes:
49 data:
50 name: orchard-search-data
51
52networks:
53 edge:
54 name: orchard-edge
55 external: true