|
c588255…
|
ragelink
|
1 |
# Fossilrepo |
|
c588255…
|
ragelink
|
2 |
|
|
c588255…
|
ragelink
|
3 |
**Self-hosted Fossil forge with a modern web interface.** |
|
c588255…
|
ragelink
|
4 |
|
|
6c1d3dd…
|
ragelink
|
5 |
 |
|
6c1d3dd…
|
ragelink
|
6 |
|
|
c588255…
|
ragelink
|
7 |
Fossilrepo wraps [Fossil SCM](https://fossil-scm.org) with a Django + HTMX management layer, replacing Fossil's built-in web UI with a GitHub/GitLab-caliber experience while preserving everything that makes Fossil unique: single-file repos, built-in wiki, tickets, forum, and technotes. |
|
6c1d3dd…
|
ragelink
|
8 |
|
|
6c1d3dd…
|
ragelink
|
9 |
**Live instance:** [fossilrepo.io](https://fossilrepo.io) | **Docs:** [fossilrepo.dev](https://fossilrepo.dev) | **Powered by [BoilerWorks](https://boilerworks.ai)** |
|
c588255…
|
ragelink
|
10 |
|
|
c588255…
|
ragelink
|
11 |
## Why Fossilrepo? |
|
c588255…
|
ragelink
|
12 |
|
|
c588255…
|
ragelink
|
13 |
Fossil is the most underrated version control system. Every repository is a single SQLite file containing your code, wiki, tickets, forum, and technotes. No external services, no complex setup. But its web UI hasn't changed since 1998. |
|
c588255…
|
ragelink
|
14 |
|
|
c588255…
|
ragelink
|
15 |
Fossilrepo fixes that. You get: |
|
c588255…
|
ragelink
|
16 |
|
|
c588255…
|
ragelink
|
17 |
- A modern dark/light UI built with Django, HTMX, Alpine.js, and Tailwind CSS |
|
c588255…
|
ragelink
|
18 |
- GitHub-style code browser with line numbers, blame, history, and syntax highlighting |
|
c588255…
|
ragelink
|
19 |
- Timeline with DAG graph showing fork/merge connectors and color-coded branches |
|
c588255…
|
ragelink
|
20 |
- Full ticket CRUD with filters, comments, and CSV export |
|
c588255…
|
ragelink
|
21 |
- Wiki with Markdown + Fossil markup + Pikchr diagram rendering |
|
c588255…
|
ragelink
|
22 |
- Forum with threaded discussions |
|
c588255…
|
ragelink
|
23 |
- Releases with file attachments and markdown changelogs |
|
c588255…
|
ragelink
|
24 |
- Git mirror sync to GitHub/GitLab via OAuth |
|
c588255…
|
ragelink
|
25 |
- Clone/push/pull over HTTP and SSH through Django's auth layer |
|
c588255…
|
ragelink
|
26 |
- Webhook dispatch with HMAC signing and delivery logs |
|
c588255…
|
ragelink
|
27 |
- Omnibus Docker image with Fossil compiled from source |
|
4ce269c…
|
ragelink
|
28 |
|
|
c588255…
|
ragelink
|
29 |
All while Fossil remains the source of truth. Fossilrepo reads `.fossil` files directly via SQLite for speed, and uses the `fossil` CLI for writes to preserve artifact integrity. |
|
4ce269c…
|
ragelink
|
30 |
|
|
4ce269c…
|
ragelink
|
31 |
## Stack |
|
4ce269c…
|
ragelink
|
32 |
|
|
4ce269c…
|
ragelink
|
33 |
| Layer | Technology | |
|
4ce269c…
|
ragelink
|
34 |
|-------|-----------| |
|
4ce269c…
|
ragelink
|
35 |
| Backend | Django 5 (Python 3.12+) | |
|
c588255…
|
ragelink
|
36 |
| Frontend | HTMX 2.0 + Alpine.js 3 + Tailwind CSS (CDN) | |
|
c588255…
|
ragelink
|
37 |
| Database | PostgreSQL 16 (app data) + SQLite (Fossil repos) | |
|
4ce269c…
|
ragelink
|
38 |
| Cache/Broker | Redis 7 | |
|
c588255…
|
ragelink
|
39 |
| Jobs | Celery + Redis | |
|
4ce269c…
|
ragelink
|
40 |
| Auth | Session-based (httpOnly cookies) | |
|
c588255…
|
ragelink
|
41 |
| SCM | Fossil 2.24 (compiled from source in Docker) | |
|
4ce269c…
|
ragelink
|
42 |
| Linter | Ruff | |
|
4ce269c…
|
ragelink
|
43 |
|
|
4ce269c…
|
ragelink
|
44 |
## Quick Start |
|
4ce269c…
|
ragelink
|
45 |
|
|
4ce269c…
|
ragelink
|
46 |
```bash |
|
c588255…
|
ragelink
|
47 |
git clone https://github.com/ConflictHQ/fossilrepo.git |
|
c588255…
|
ragelink
|
48 |
cd fossilrepo |
|
4ce269c…
|
ragelink
|
49 |
docker compose up -d --build |
|
4ce269c…
|
ragelink
|
50 |
|
|
c588255…
|
ragelink
|
51 |
# Run migrations and seed sample data |
|
4ce269c…
|
ragelink
|
52 |
docker compose exec backend python manage.py migrate |
|
4ce269c…
|
ragelink
|
53 |
docker compose exec backend python manage.py seed |
|
4ce269c…
|
ragelink
|
54 |
|
|
4ce269c…
|
ragelink
|
55 |
# Open the app |
|
4ce269c…
|
ragelink
|
56 |
open http://localhost:8000 |
|
4ce269c…
|
ragelink
|
57 |
``` |
|
4ce269c…
|
ragelink
|
58 |
|
|
c588255…
|
ragelink
|
59 |
**Default users:** `admin` / `admin` (superuser) and `viewer` / `viewer` (read-only). |
|
c588255…
|
ragelink
|
60 |
|
|
c588255…
|
ragelink
|
61 |
## Features |
|
c588255…
|
ragelink
|
62 |
|
|
c588255…
|
ragelink
|
63 |
### Code Browser |
|
c588255…
|
ragelink
|
64 |
- Directory navigation with breadcrumbs |
|
c588255…
|
ragelink
|
65 |
- Syntax-highlighted source view with line numbers and permalinks |
|
c588255…
|
ragelink
|
66 |
- Blame with age-based coloring (newest = brand red, oldest = gray) |
|
c588255…
|
ragelink
|
67 |
- File history, raw download, rendered preview for Markdown/HTML |
|
c588255…
|
ragelink
|
68 |
|
|
c588255…
|
ragelink
|
69 |
### Timeline |
|
c588255…
|
ragelink
|
70 |
- DAG graph with fork/merge connectors, color-coded branches |
|
c588255…
|
ragelink
|
71 |
- Merge commit diamonds, leaf indicators |
|
c588255…
|
ragelink
|
72 |
- Keyboard navigation (j/k/Enter), HTMX infinite scroll |
|
c588255…
|
ragelink
|
73 |
- RSS feed |
|
c588255…
|
ragelink
|
74 |
|
|
c588255…
|
ragelink
|
75 |
### Diffs |
|
c588255…
|
ragelink
|
76 |
- Unified and side-by-side view (toggle with localStorage preference) |
|
c588255…
|
ragelink
|
77 |
- Syntax highlighting via highlight.js |
|
c588255…
|
ragelink
|
78 |
- Line-level permalinks |
|
c588255…
|
ragelink
|
79 |
- Compare any two checkins |
|
c588255…
|
ragelink
|
80 |
|
|
c588255…
|
ragelink
|
81 |
### Tickets |
|
c588255…
|
ragelink
|
82 |
- Filter by status, type, priority, severity |
|
c588255…
|
ragelink
|
83 |
- Full CRUD: create, edit, close/reopen, comment |
|
c588255…
|
ragelink
|
84 |
- CSV export |
|
c588255…
|
ragelink
|
85 |
- Pagination with configurable page size |
|
c588255…
|
ragelink
|
86 |
|
|
c588255…
|
ragelink
|
87 |
### Wiki |
|
c588255…
|
ragelink
|
88 |
- Markdown + Fossil wiki markup + raw HTML |
|
c588255…
|
ragelink
|
89 |
- Pikchr diagram rendering |
|
c588255…
|
ragelink
|
90 |
- Right-sidebar table of contents |
|
c588255…
|
ragelink
|
91 |
- Create and edit pages |
|
c588255…
|
ragelink
|
92 |
|
|
c588255…
|
ragelink
|
93 |
### Forum |
|
c588255…
|
ragelink
|
94 |
- Threaded discussions (Fossil-native + Django-backed posts) |
|
c588255…
|
ragelink
|
95 |
- Create threads, post replies |
|
c588255…
|
ragelink
|
96 |
- Markdown body with preview |
|
c588255…
|
ragelink
|
97 |
|
|
c588255…
|
ragelink
|
98 |
### Releases |
|
c588255…
|
ragelink
|
99 |
- Versioned releases with tag names and markdown changelogs |
|
c588255…
|
ragelink
|
100 |
- File attachments with download counts |
|
c588255…
|
ragelink
|
101 |
- Draft and prerelease support |
|
c588255…
|
ragelink
|
102 |
|
|
c588255…
|
ragelink
|
103 |
### Sync |
|
c588255…
|
ragelink
|
104 |
- Pull from upstream Fossil remotes |
|
c588255…
|
ragelink
|
105 |
- Git mirror to GitHub/GitLab (OAuth or SSH key auth) |
|
c588255…
|
ragelink
|
106 |
- Clone/push/pull over HTTP via `fossil http` CGI proxy |
|
c588255…
|
ragelink
|
107 |
- SSH push via restricted sshd (port 2222) |
|
c588255…
|
ragelink
|
108 |
- Configurable sync modes: on-change, scheduled, both |
|
c588255…
|
ragelink
|
109 |
|
|
c588255…
|
ragelink
|
110 |
### Webhooks |
|
c588255…
|
ragelink
|
111 |
- Outbound webhooks on checkin, ticket, wiki, and release events |
|
c588255…
|
ragelink
|
112 |
- HMAC-SHA256 signed payloads |
|
c588255…
|
ragelink
|
113 |
- Exponential backoff retry (3 attempts) |
|
c588255…
|
ragelink
|
114 |
- Delivery log with response status and timing |
|
c588255…
|
ragelink
|
115 |
|
|
c588255…
|
ragelink
|
116 |
### Organization |
|
c588255…
|
ragelink
|
117 |
- Single-org model with teams and members |
|
c588255…
|
ragelink
|
118 |
- User CRUD: create, edit, deactivate, change password |
|
c588255…
|
ragelink
|
119 |
- Team management with member assignment |
|
c588255…
|
ragelink
|
120 |
- Project-level team roles: read, write, admin |
|
c588255…
|
ragelink
|
121 |
- Project visibility: public, internal, private |
|
c588255…
|
ragelink
|
122 |
|
|
c588255…
|
ragelink
|
123 |
### Infrastructure |
|
c588255…
|
ragelink
|
124 |
- Omnibus Docker image (Fossil compiled from source) |
|
c588255…
|
ragelink
|
125 |
- Caddy for SSL termination and subdomain routing |
|
c588255…
|
ragelink
|
126 |
- Litestream for continuous SQLite-to-S3 replication |
|
c588255…
|
ragelink
|
127 |
- Celery Beat for scheduled metadata sync and upstream checks |
|
c588255…
|
ragelink
|
128 |
- Encrypted credential storage (Fernet/AES-128-CBC at rest) |
|
4ce269c…
|
ragelink
|
129 |
|
|
4ce269c…
|
ragelink
|
130 |
## Architecture |
|
4ce269c…
|
ragelink
|
131 |
|
|
4ce269c…
|
ragelink
|
132 |
``` |
|
4ce269c…
|
ragelink
|
133 |
Browser |
|
c588255…
|
ragelink
|
134 |
| |
|
c588255…
|
ragelink
|
135 |
v |
|
c588255…
|
ragelink
|
136 |
Django 5 + HTMX + Alpine.js + Tailwind CSS |
|
c588255…
|
ragelink
|
137 |
| |
|
c588255…
|
ragelink
|
138 |
|-- FossilReader (direct SQLite reads from .fossil files) |
|
c588255…
|
ragelink
|
139 |
|-- FossilCLI (subprocess wrapper for write operations) |
|
c588255…
|
ragelink
|
140 |
|-- fossil http (CGI proxy for clone/push/pull) |
|
c588255…
|
ragelink
|
141 |
| |
|
c588255…
|
ragelink
|
142 |
|-- PostgreSQL 16 (orgs, users, teams, projects, settings) |
|
c588255…
|
ragelink
|
143 |
|-- Redis 7 (Celery broker, cache) |
|
c588255…
|
ragelink
|
144 |
|-- Celery (background sync, webhooks, notifications) |
|
c588255…
|
ragelink
|
145 |
| |
|
c588255…
|
ragelink
|
146 |
v |
|
c588255…
|
ragelink
|
147 |
.fossil files (SQLite — code + wiki + tickets + forum + technotes) |
|
c588255…
|
ragelink
|
148 |
| |
|
c588255…
|
ragelink
|
149 |
v |
|
c588255…
|
ragelink
|
150 |
Litestream --> S3 (continuous backup) |
|
4ce269c…
|
ragelink
|
151 |
``` |
|
4ce269c…
|
ragelink
|
152 |
|
|
c588255…
|
ragelink
|
153 |
No separate frontend service. Django serves everything: templates, static files, and HTMX partials. |
|
c588255…
|
ragelink
|
154 |
|
|
c588255…
|
ragelink
|
155 |
## Configuration |
|
c588255…
|
ragelink
|
156 |
|
|
c588255…
|
ragelink
|
157 |
All runtime settings are configurable via Django admin (Constance): |
|
c588255…
|
ragelink
|
158 |
|
|
c588255…
|
ragelink
|
159 |
| Setting | Default | Description | |
|
c588255…
|
ragelink
|
160 |
|---------|---------|-------------| |
|
c588255…
|
ragelink
|
161 |
| `SITE_NAME` | Fossilrepo | Display name | |
|
c588255…
|
ragelink
|
162 |
| `FOSSIL_DATA_DIR` | /data/repos | Where .fossil files live | |
|
c588255…
|
ragelink
|
163 |
| `FOSSIL_BINARY_PATH` | fossil | Path to the fossil binary | |
|
c588255…
|
ragelink
|
164 |
| `FOSSIL_STORE_IN_DB` | false | Store .fossil snapshots via Django file storage | |
|
c588255…
|
ragelink
|
165 |
| `FOSSIL_S3_TRACKING` | false | Track S3/Litestream replication | |
|
c588255…
|
ragelink
|
166 |
| `GIT_SYNC_MODE` | disabled | Default sync mode for new mirrors | |
|
c588255…
|
ragelink
|
167 |
| `GIT_SYNC_SCHEDULE` | */15 * * * * | Default cron for scheduled sync | |
|
c588255…
|
ragelink
|
168 |
|
|
c588255…
|
ragelink
|
169 |
See [`.env.example`](.env.example) for all environment variables and [`.env.production.example`](.env.production.example) for production configuration. |
|
4ce269c…
|
ragelink
|
170 |
|
|
4ce269c…
|
ragelink
|
171 |
## Development |
|
4ce269c…
|
ragelink
|
172 |
|
|
4ce269c…
|
ragelink
|
173 |
```bash |
|
4ce269c…
|
ragelink
|
174 |
# Local development (without Docker) |
|
4ce269c…
|
ragelink
|
175 |
uv sync --all-extras |
|
c588255…
|
ragelink
|
176 |
DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver |
|
4ce269c…
|
ragelink
|
177 |
|
|
4ce269c…
|
ragelink
|
178 |
# Run tests |
|
c588255…
|
ragelink
|
179 |
DJANGO_DEBUG=true uv run pytest |
|
4ce269c…
|
ragelink
|
180 |
|
|
c588255…
|
ragelink
|
181 |
# Lint |
|
c588255…
|
ragelink
|
182 |
ruff check . && ruff format --check . |
|
4ce269c…
|
ragelink
|
183 |
``` |
|
4ce269c…
|
ragelink
|
184 |
|
|
c588255…
|
ragelink
|
185 |
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full development guide and [`bootstrap.md`](bootstrap.md) for codebase conventions. |
|
c588255…
|
ragelink
|
186 |
|
|
c588255…
|
ragelink
|
187 |
## License |
|
c588255…
|
ragelink
|
188 |
|
|
c588255…
|
ragelink
|
189 |
MIT License. See [LICENSE](LICENSE) for details. |
|
4ce269c…
|
ragelink
|
190 |
|
|
4ce269c…
|
ragelink
|
191 |
--- |
|
4ce269c…
|
ragelink
|
192 |
|
|
c588255…
|
ragelink
|
193 |
Built by [CONFLICT](https://weareconflict.com). Fossilrepo is open source under the MIT license. |