Artifact d42a1b919dc6eafbd719cff61a5c9c71337e3d9b56a157ab6b8112517719802f:
- File CLAUDE.md — part of check-in [81dd1146bc] at 2026-03-14 23:18:19 on branch trunk — Initial commit: dark skin, a11y.js, landing page, Caddyfile (user: dmestas, size: 4426) [annotate] [blame] [check-ins using]
Fossil SCM Hub — /var/fossil
Self-hosted multi-repo Fossil SCM server for craftdesign.group.
Architecture
https://fossil.craftdesign.group
↓ Cloudflare named tunnel (fossil / 45ea54d2-1b49-496b-bc35-c01c45d95297)
Caddy :8090
├── GET / → /var/fossil/www/index.html (dark landing page)
└── /* → proxy to Fossil :8081
Fossil :8081 (localhost only)
└── serves /var/fossil/repos/*.fossil (multi-repo directory mode)
Directory Layout
/var/fossil/
├── repos/ # all .fossil repo files (auto-served by fossil)
│ ├── edgesync.fossil
│ └── go-libfossil.fossil
├── skin/ # shared skin — push to repos via script below
│ ├── header.txt # TH1 template
│ ├── footer.txt
│ └── css.txt # dark theme matching landing page
├── www/
│ └── index.html # custom landing page (dark theme)
├── Caddyfile # Caddy reverse proxy config
└── CLAUDE.md # this file
Systemd Services
All three are enabled and start on boot.
| Service | Command |
|---|---|
fossil.service |
fossil server /var/fossil/repos --port 8081 --localhost --repolist --https --baseurl https://fossil.craftdesign.group --notfound / |
caddy-fossil.service |
caddy run --config /var/fossil/Caddyfile |
cloudflared-fossil.service |
cloudflared tunnel --config ~/.cloudflared/config.yml run |
sudo systemctl status fossil caddy-fossil cloudflared-fossil
sudo systemctl restart fossil caddy-fossil cloudflared-fossil
sudo journalctl -u fossil -f
Repositories
| Name | URL | Admin password |
|---|---|---|
| edgesync | https://fossil.craftdesign.group/edgesync/ | set via /edgesync/setup_alist |
| go-libfossil | https://fossil.craftdesign.group/go-libfossil/ | set via /go-libfossil/setup_alist |
Admin user: dmestas
Adding a Repository
# 1. Init on server
fossil init /var/fossil/repos/<name>.fossil
# 2. Apply the skin
python3 /var/fossil/skin/apply.py
# 3. Add a card to /var/fossil/www/index.html
# From local machine:
fossil clone https://[email protected]/<name>/ <name>.fossil
# or push existing:
fossil remote add hub https://[email protected]/<name>/
fossil push hub
Skin
Dark theme matching the landing page. Design tokens:
--bg: #0f1117/--surface: #1a1d27/--border: #2a2d3e--accent: #6c8ebf/--text: #e2e8f0/--muted: #8892a4- Fonts: Inter (body), JetBrains Mono (code)
The skin lives in /var/fossil/skin/ and must be written into each repo's
SQLite config table (keys: css, header, footer). After editing skin files, push with:
python3 << 'EOF'
import sqlite3, time, os, glob
REPOS = glob.glob("/var/fossil/repos/*.fossil")
SKIN_DIR = "/var/fossil/skin"
parts = {
"css": open(f"{SKIN_DIR}/css.txt").read(),
"header": open(f"{SKIN_DIR}/header.txt").read(),
"footer": open(f"{SKIN_DIR}/footer.txt").read(),
}
mtime = int(time.time())
for repo in REPOS:
con = sqlite3.connect(repo)
for name, value in parts.items():
con.execute("INSERT OR REPLACE INTO config(name,value,mtime) VALUES(?,?,?)",
(name, value, mtime))
con.commit()
con.close()
print(f"skinned {os.path.basename(repo)}")
EOF
Cloudflare Tunnel
- Tunnel name:
fossil - Tunnel ID:
45ea54d2-1b49-496b-bc35-c01c45d95297 - Config:
~/.cloudflared/config.yml(points to Caddy :8090) - Credentials:
~/.cloudflared/45ea54d2-….json - DNS CNAME managed automatically by cloudflared
Installed Versions
- Fossil 2.28 —
/usr/local/bin/fossil(built from source tarball) - Caddy 2.9.1 —
/usr/local/bin/caddy - cloudflared 2026.3.0 —
/usr/local/bin/cloudflared
Known Gotchas
- Fossil skin keys are
css/header/footer(noskin:prefix) — written directly to each repo's SQLiteconfigtable --httpsflag is required onfossil serverwhen behind a reverse proxy — without it Fossil generates http:// redirect loops- Skins are per-repo; adding a new repo requires running the apply script
- Port 8080 is taken by Coolify's Traefik proxy — Fossil runs on 8081
- The repo listing page (
/) has no skin — it's replaced entirely by Caddy serving the staticindex.html