FossilRepo
Add fossilrepo.dev documentation site (MkDocs Material, GitHub Pages) DNS configured via porkbun-cli, CONFLICT brand styles from planopticon.dev, getting-started guides, architecture docs, and CI workflow for auto-deploy.
Commit
350f2f5afe8784c3b95c70253618f3b5a32ef8dc415e07067ea788f905cb5f76
Parent
63753cf52337eae…
11 files changed
+42
+1
+1
+98
+79
+96
+75
+115
+81
+63
+84
+
.github/workflows/docs.yaml
~
.gitignore
+
docs/CNAME
+
docs/architecture/overview.md
+
docs/architecture/sync-bridge.md
+
docs/getting-started/configuration.md
+
docs/getting-started/first-repo.md
+
docs/getting-started/installation.md
+
docs/getting-started/prerequisites.md
+
docs/index.md
+
mkdocs.yml
| --- a/.github/workflows/docs.yaml | ||
| +++ b/.github/workflows/docs.yaml | ||
| @@ -0,0 +1,42 @@ | ||
| 1 | +name: Docs | |
| 2 | + | |
| 3 | +on: | |
| 4 | + push: | |
| 5 | + branches: [main] | |
| 6 | + paths: | |
| 7 | + - 'docs/**' | |
| 8 | + - 'mkdocs.yml' | |
| 9 | + - '.github/workflows/docs.yaml' | |
| 10 | + | |
| 11 | +permissions: | |
| 12 | + contents: read | |
| 13 | + pages: write | |
| 14 | + id-token: write | |
| 15 | + | |
| 16 | +concurrency: | |
| 17 | + group: pages | |
| 18 | + cancel-in-progress: true | |
| 19 | + | |
| 20 | +jobs: | |
| 21 | + build: | |
| 22 | + runs-on: ubuntu-latest | |
| 23 | + steps: | |
| 24 | + - uses: actions/checkout@v4 | |
| 25 | + - uses: actions/setup-python@v5 | |
| 26 | + with: | |
| 27 | + python-version: "3.12" | |
| 28 | + - run: pip install mkdocs-material | |
| 29 | + - run: mkdocs build --strict | |
| 30 | + - uses: actions/upload-pages-artifact@v3 | |
| 31 | + with: | |
| 32 | + path: site | |
| 33 | + | |
| 34 | + deploy: | |
| 35 | + needs: build | |
| 36 | + runs-on: ubuntu-latest | |
| 37 | + environment: | |
| 38 | + name: github-pages | |
| 39 | + url: ${{ steps.deployment.outputs.page_url }} | |
| 40 | + steps: | |
| 41 | + - id: deployment | |
| 42 | + uses: actions/deploy-pages@v4 |
| --- a/.github/workflows/docs.yaml | |
| +++ b/.github/workflows/docs.yaml | |
| @@ -0,0 +1,42 @@ | |
| --- a/.github/workflows/docs.yaml | |
| +++ b/.github/workflows/docs.yaml | |
| @@ -0,0 +1,42 @@ | |
| 1 | name: Docs |
| 2 | |
| 3 | on: |
| 4 | push: |
| 5 | branches: [main] |
| 6 | paths: |
| 7 | - 'docs/**' |
| 8 | - 'mkdocs.yml' |
| 9 | - '.github/workflows/docs.yaml' |
| 10 | |
| 11 | permissions: |
| 12 | contents: read |
| 13 | pages: write |
| 14 | id-token: write |
| 15 | |
| 16 | concurrency: |
| 17 | group: pages |
| 18 | cancel-in-progress: true |
| 19 | |
| 20 | jobs: |
| 21 | build: |
| 22 | runs-on: ubuntu-latest |
| 23 | steps: |
| 24 | - uses: actions/checkout@v4 |
| 25 | - uses: actions/setup-python@v5 |
| 26 | with: |
| 27 | python-version: "3.12" |
| 28 | - run: pip install mkdocs-material |
| 29 | - run: mkdocs build --strict |
| 30 | - uses: actions/upload-pages-artifact@v3 |
| 31 | with: |
| 32 | path: site |
| 33 | |
| 34 | deploy: |
| 35 | needs: build |
| 36 | runs-on: ubuntu-latest |
| 37 | environment: |
| 38 | name: github-pages |
| 39 | url: ${{ steps.deployment.outputs.page_url }} |
| 40 | steps: |
| 41 | - id: deployment |
| 42 | uses: actions/deploy-pages@v4 |
+1
| --- .gitignore | ||
| +++ .gitignore | ||
| @@ -26,5 +26,6 @@ | ||
| 26 | 26 | node_modules/ |
| 27 | 27 | runtime/ |
| 28 | 28 | assets/ |
| 29 | 29 | fossilrepo.fossil |
| 30 | 30 | .fslckout |
| 31 | +site/ | |
| 31 | 32 | |
| 32 | 33 | ADDED docs/CNAME |
| 33 | 34 | ADDED docs/architecture/overview.md |
| 34 | 35 | ADDED docs/architecture/sync-bridge.md |
| 35 | 36 | ADDED docs/getting-started/configuration.md |
| 36 | 37 | ADDED docs/getting-started/first-repo.md |
| 37 | 38 | ADDED docs/getting-started/installation.md |
| 38 | 39 | ADDED docs/getting-started/prerequisites.md |
| 39 | 40 | ADDED docs/index.md |
| 40 | 41 | ADDED mkdocs.yml |
| --- .gitignore | |
| +++ .gitignore | |
| @@ -26,5 +26,6 @@ | |
| 26 | node_modules/ |
| 27 | runtime/ |
| 28 | assets/ |
| 29 | fossilrepo.fossil |
| 30 | .fslckout |
| 31 | |
| 32 | DDED docs/CNAME |
| 33 | DDED docs/architecture/overview.md |
| 34 | DDED docs/architecture/sync-bridge.md |
| 35 | DDED docs/getting-started/configuration.md |
| 36 | DDED docs/getting-started/first-repo.md |
| 37 | DDED docs/getting-started/installation.md |
| 38 | DDED docs/getting-started/prerequisites.md |
| 39 | DDED docs/index.md |
| 40 | DDED mkdocs.yml |
| --- .gitignore | |
| +++ .gitignore | |
| @@ -26,5 +26,6 @@ | |
| 26 | node_modules/ |
| 27 | runtime/ |
| 28 | assets/ |
| 29 | fossilrepo.fossil |
| 30 | .fslckout |
| 31 | site/ |
| 32 | |
| 33 | DDED docs/CNAME |
| 34 | DDED docs/architecture/overview.md |
| 35 | DDED docs/architecture/sync-bridge.md |
| 36 | DDED docs/getting-started/configuration.md |
| 37 | DDED docs/getting-started/first-repo.md |
| 38 | DDED docs/getting-started/installation.md |
| 39 | DDED docs/getting-started/prerequisites.md |
| 40 | DDED docs/index.md |
| 41 | DDED mkdocs.yml |
+1
| --- a/docs/CNAME | ||
| +++ b/docs/CNAME | ||
| @@ -0,0 +1 @@ | ||
| 1 | +fossilrepo.dev |
| --- a/docs/CNAME | |
| +++ b/docs/CNAME | |
| @@ -0,0 +1 @@ | |
| --- a/docs/CNAME | |
| +++ b/docs/CNAME | |
| @@ -0,0 +1 @@ | |
| 1 | fossilrepo.dev |
| --- a/docs/architecture/overview.md | ||
| +++ b/docs/architecture/overview.md | ||
| @@ -0,0 +1,98 @@ | ||
| 1 | +# Architecture Overview | |
| 2 | + | |
| 3 | +Fossilrepo is a thin orchestration layer around Fossil SCM. Fossil does the heavy lifting -- fossilrepo handles provisioning, routing, backups, and the management UI. | |
| 4 | + | |
| 5 | +## System Diagram | |
| 6 | + | |
| 7 | +```mermaid | |
| 8 | +graph TB | |
| 9 | + subgraph Internet | |
| 10 | + User[User / Browser] | |
| 11 | + end | |
| 12 | + | |
| 13 | + subgraph Fossilrepo Server | |
| 14 | + Caddy[Caddy<br/>SSL + Routing] | |
| 15 | + Django[Django<br/>Management UI] | |
| 16 | + Fossil[Fossil Server<br/>--repolist] | |
| 17 | + Celery[Celery Workers] | |
| 18 | + Redis[Redis] | |
| 19 | + Postgres[(PostgreSQL)] | |
| 20 | + Litestream[Litestream] | |
| 21 | + end | |
| 22 | + | |
| 23 | + subgraph Storage | |
| 24 | + Repos["/data/repos/<br/>*.fossil files"] | |
| 25 | + S3[(S3 / MinIO)] | |
| 26 | + end | |
| 27 | + | |
| 28 | + subgraph Mirrors | |
| 29 | + GitHub[GitHub] | |
| 30 | + GitLab[GitLab] | |
| 31 | + end | |
| 32 | + | |
| 33 | + User --> Caddy | |
| 34 | + Caddy -->|"app.domain.com"| Django | |
| 35 | + Caddy -->|"repo.domain.com"| Fossil | |
| 36 | + Django --> Postgres | |
| 37 | + Django --> Redis | |
| 38 | + Celery --> Redis | |
| 39 | + Celery -->|sync bridge| GitHub | |
| 40 | + Celery -->|sync bridge| GitLab | |
| 41 | + Fossil --> Repos | |
| 42 | + Litestream --> Repos | |
| 43 | + Litestream --> S3 | |
| 44 | +``` | |
| 45 | + | |
| 46 | +## Components | |
| 47 | + | |
| 48 | +### Fossil Server | |
| 49 | + | |
| 50 | +A single `fossil server --repolist /data/repos/` process serves all repositories. Each `.fossil` file is a self-contained SQLite database with VCS history, issues, wiki, and forum. | |
| 51 | + | |
| 52 | +Adding a new repo is just `fossil init /data/repos/name.fossil` -- no restart needed. | |
| 53 | + | |
| 54 | +### Caddy | |
| 55 | + | |
| 56 | +Handles SSL termination and subdomain routing: | |
| 57 | + | |
| 58 | +- `your-domain.com` routes to the Django management UI | |
| 59 | +- `reponame.your-domain.com` routes directly to Fossil's web UI | |
| 60 | + | |
| 61 | +Caddy automatically provisions and renews Let's Encrypt certificates. | |
| 62 | + | |
| 63 | +### Django Management Layer | |
| 64 | + | |
| 65 | +Provides the administrative interface: | |
| 66 | + | |
| 67 | +- Repository lifecycle (create, configure, archive) | |
| 68 | +- User and organization management | |
| 69 | +- Dashboard and analytics | |
| 70 | +- Sync bridge configuration | |
| 71 | + | |
| 72 | +Django uses HTMX for interactive UI without a JavaScript framework. | |
| 73 | + | |
| 74 | +### Litestream | |
| 75 | + | |
| 76 | +Continuously replicates every `.fossil` SQLite file to S3-compatible storage. Provides: | |
| 77 | + | |
| 78 | +- **Continuous backup** -- WAL frames replicated in near-real-time | |
| 79 | +- **Point-in-time recovery** -- restore to any moment, not just snapshots | |
| 80 | +- **Zero-config per repo** -- new `.fossil` files are picked up automatically | |
| 81 | + | |
| 82 | +### Celery Workers | |
| 83 | + | |
| 84 | +Handle background tasks: | |
| 85 | + | |
| 86 | +- Sync bridge execution (Fossil to Git mirroring) | |
| 87 | +- Scheduled sync jobs | |
| 88 | +- Upstream pull operations | |
| 89 | + | |
| 90 | +## Data Flow | |
| 91 | + | |
| 92 | +1. **User pushes to Fossil** -- standard `fossil push` or `fossil sync` | |
| 93 | +2. **Fossil writes to `.fossil` file** -- SQLite transactions | |
| 94 | +3. **Litestream replicates** -- WAL frames streamed to S3 | |
| 95 | +4. **Sync bridge runs** -- Celery task mirrors changes to Git remotes | |
| 96 | +5. **Django reflects state** -- reads from Fossil SQLite for dashboards | |
| 97 | + | |
| 98 | +Fossil is always the source of truth. Everything else is derived. |
| --- a/docs/architecture/overview.md | |
| +++ b/docs/architecture/overview.md | |
| @@ -0,0 +1,98 @@ | |
| --- a/docs/architecture/overview.md | |
| +++ b/docs/architecture/overview.md | |
| @@ -0,0 +1,98 @@ | |
| 1 | # Architecture Overview |
| 2 | |
| 3 | Fossilrepo is a thin orchestration layer around Fossil SCM. Fossil does the heavy lifting -- fossilrepo handles provisioning, routing, backups, and the management UI. |
| 4 | |
| 5 | ## System Diagram |
| 6 | |
| 7 | ```mermaid |
| 8 | graph TB |
| 9 | subgraph Internet |
| 10 | User[User / Browser] |
| 11 | end |
| 12 | |
| 13 | subgraph Fossilrepo Server |
| 14 | Caddy[Caddy<br/>SSL + Routing] |
| 15 | Django[Django<br/>Management UI] |
| 16 | Fossil[Fossil Server<br/>--repolist] |
| 17 | Celery[Celery Workers] |
| 18 | Redis[Redis] |
| 19 | Postgres[(PostgreSQL)] |
| 20 | Litestream[Litestream] |
| 21 | end |
| 22 | |
| 23 | subgraph Storage |
| 24 | Repos["/data/repos/<br/>*.fossil files"] |
| 25 | S3[(S3 / MinIO)] |
| 26 | end |
| 27 | |
| 28 | subgraph Mirrors |
| 29 | GitHub[GitHub] |
| 30 | GitLab[GitLab] |
| 31 | end |
| 32 | |
| 33 | User --> Caddy |
| 34 | Caddy -->|"app.domain.com"| Django |
| 35 | Caddy -->|"repo.domain.com"| Fossil |
| 36 | Django --> Postgres |
| 37 | Django --> Redis |
| 38 | Celery --> Redis |
| 39 | Celery -->|sync bridge| GitHub |
| 40 | Celery -->|sync bridge| GitLab |
| 41 | Fossil --> Repos |
| 42 | Litestream --> Repos |
| 43 | Litestream --> S3 |
| 44 | ``` |
| 45 | |
| 46 | ## Components |
| 47 | |
| 48 | ### Fossil Server |
| 49 | |
| 50 | A single `fossil server --repolist /data/repos/` process serves all repositories. Each `.fossil` file is a self-contained SQLite database with VCS history, issues, wiki, and forum. |
| 51 | |
| 52 | Adding a new repo is just `fossil init /data/repos/name.fossil` -- no restart needed. |
| 53 | |
| 54 | ### Caddy |
| 55 | |
| 56 | Handles SSL termination and subdomain routing: |
| 57 | |
| 58 | - `your-domain.com` routes to the Django management UI |
| 59 | - `reponame.your-domain.com` routes directly to Fossil's web UI |
| 60 | |
| 61 | Caddy automatically provisions and renews Let's Encrypt certificates. |
| 62 | |
| 63 | ### Django Management Layer |
| 64 | |
| 65 | Provides the administrative interface: |
| 66 | |
| 67 | - Repository lifecycle (create, configure, archive) |
| 68 | - User and organization management |
| 69 | - Dashboard and analytics |
| 70 | - Sync bridge configuration |
| 71 | |
| 72 | Django uses HTMX for interactive UI without a JavaScript framework. |
| 73 | |
| 74 | ### Litestream |
| 75 | |
| 76 | Continuously replicates every `.fossil` SQLite file to S3-compatible storage. Provides: |
| 77 | |
| 78 | - **Continuous backup** -- WAL frames replicated in near-real-time |
| 79 | - **Point-in-time recovery** -- restore to any moment, not just snapshots |
| 80 | - **Zero-config per repo** -- new `.fossil` files are picked up automatically |
| 81 | |
| 82 | ### Celery Workers |
| 83 | |
| 84 | Handle background tasks: |
| 85 | |
| 86 | - Sync bridge execution (Fossil to Git mirroring) |
| 87 | - Scheduled sync jobs |
| 88 | - Upstream pull operations |
| 89 | |
| 90 | ## Data Flow |
| 91 | |
| 92 | 1. **User pushes to Fossil** -- standard `fossil push` or `fossil sync` |
| 93 | 2. **Fossil writes to `.fossil` file** -- SQLite transactions |
| 94 | 3. **Litestream replicates** -- WAL frames streamed to S3 |
| 95 | 4. **Sync bridge runs** -- Celery task mirrors changes to Git remotes |
| 96 | 5. **Django reflects state** -- reads from Fossil SQLite for dashboards |
| 97 | |
| 98 | Fossil is always the source of truth. Everything else is derived. |
| --- a/docs/architecture/sync-bridge.md | ||
| +++ b/docs/architecture/sync-bridge.md | ||
| @@ -0,0 +1,79 @@ | ||
| 1 | +# Sync Bridge | |
| 2 | + | |
| 3 | +The sync bridge mirrors Fossil repositories to GitHub and GitLab as downstream read-only copies. | |
| 4 | + | |
| 5 | +## How It Works | |
| 6 | + | |
| 7 | +```mermaid | |
| 8 | +flowchart LR | |
| 9 | + Fossil["Fossil Repo<br/>(source of truth)"] --> Bridge["Sync Bridge<br/>(Celery task)"] | |
| 10 | + Bridge --> Git["Git Export"] | |
| 11 | + Git --> GitHub["GitHub Mirror"] | |
| 12 | + Git --> GitLab["GitLab Mirror"] | |
| 13 | +``` | |
| 14 | + | |
| 15 | +The bridge: | |
| 16 | + | |
| 17 | +1. Exports Fossil commits as Git commits | |
| 18 | +2. Pushes to configured Git remotes | |
| 19 | +3. Optionally syncs tickets to GitHub/GitLab Issues | |
| 20 | +4. Optionally syncs wiki pages to repo docs | |
| 21 | + | |
| 22 | +## What Gets Synced | |
| 23 | + | |
| 24 | +| Fossil Artifact | Git Target | Configurable | | |
| 25 | +|---|---|---| | |
| 26 | +| Commits | Git commits | Always | | |
| 27 | +| Tags | Git tags | Always | | |
| 28 | +| Branches | Git branches | Always | | |
| 29 | +| Tickets | GitHub/GitLab Issues | Optional | | |
| 30 | +| Wiki | Repository docs | Optional | | |
| 31 | + | |
| 32 | +## Configuration | |
| 33 | + | |
| 34 | +Set up mirroring through the Django management UI or environment variables: | |
| 35 | + | |
| 36 | +```bash | |
| 37 | +# GitHub mirror | |
| 38 | +GITHUB_TOKEN=ghp_xxxxxxxxxxxx | |
| 39 | + | |
| 40 | +# GitLab mirror | |
| 41 | +GITLAB_TOKEN=glpat-xxxxxxxxxxxx | |
| 42 | +``` | |
| 43 | + | |
| 44 | +Per-repository mirror configuration is managed in the dashboard under **Repository Settings > Sync**. | |
| 45 | + | |
| 46 | +## Sync Modes | |
| 47 | + | |
| 48 | +### On-Demand | |
| 49 | + | |
| 50 | +Trigger a sync manually from the dashboard or CLI: | |
| 51 | + | |
| 52 | +```bash | |
| 53 | +docker compose exec django python manage.py fossil_sync my-project | |
| 54 | +``` | |
| 55 | + | |
| 56 | +### Scheduled | |
| 57 | + | |
| 58 | +Configure a Celery Beat schedule to sync at regular intervals: | |
| 59 | + | |
| 60 | +```python | |
| 61 | +# Runs every 15 minutes | |
| 62 | +CELERY_BEAT_SCHEDULE = { | |
| 63 | + 'sync-all-repos': { | |
| 64 | + 'task': 'fossil.tasks.sync_all', | |
| 65 | + 'schedule': 900.0, | |
| 66 | + }, | |
| 67 | +} | |
| 68 | +``` | |
| 69 | + | |
| 70 | +### Upstream Pull | |
| 71 | + | |
| 72 | +Pull updates from a remote Fossil server into your local instance: | |
| 73 | + | |
| 74 | +```bash | |
| 75 | +docker compose exec django python manage.py fossil_pull my-project | |
| 76 | +``` | |
| 77 | + | |
| 78 | +!!! warning "Direction matters" | |
| 79 | + The sync bridge is **one-way**: Fossil to Git. Changes pushed directly to a Git mirror will be overwritten on the next sync. Always push to the Fossil repo. |
| --- a/docs/architecture/sync-bridge.md | |
| +++ b/docs/architecture/sync-bridge.md | |
| @@ -0,0 +1,79 @@ | |
| --- a/docs/architecture/sync-bridge.md | |
| +++ b/docs/architecture/sync-bridge.md | |
| @@ -0,0 +1,79 @@ | |
| 1 | # Sync Bridge |
| 2 | |
| 3 | The sync bridge mirrors Fossil repositories to GitHub and GitLab as downstream read-only copies. |
| 4 | |
| 5 | ## How It Works |
| 6 | |
| 7 | ```mermaid |
| 8 | flowchart LR |
| 9 | Fossil["Fossil Repo<br/>(source of truth)"] --> Bridge["Sync Bridge<br/>(Celery task)"] |
| 10 | Bridge --> Git["Git Export"] |
| 11 | Git --> GitHub["GitHub Mirror"] |
| 12 | Git --> GitLab["GitLab Mirror"] |
| 13 | ``` |
| 14 | |
| 15 | The bridge: |
| 16 | |
| 17 | 1. Exports Fossil commits as Git commits |
| 18 | 2. Pushes to configured Git remotes |
| 19 | 3. Optionally syncs tickets to GitHub/GitLab Issues |
| 20 | 4. Optionally syncs wiki pages to repo docs |
| 21 | |
| 22 | ## What Gets Synced |
| 23 | |
| 24 | | Fossil Artifact | Git Target | Configurable | |
| 25 | |---|---|---| |
| 26 | | Commits | Git commits | Always | |
| 27 | | Tags | Git tags | Always | |
| 28 | | Branches | Git branches | Always | |
| 29 | | Tickets | GitHub/GitLab Issues | Optional | |
| 30 | | Wiki | Repository docs | Optional | |
| 31 | |
| 32 | ## Configuration |
| 33 | |
| 34 | Set up mirroring through the Django management UI or environment variables: |
| 35 | |
| 36 | ```bash |
| 37 | # GitHub mirror |
| 38 | GITHUB_TOKEN=ghp_xxxxxxxxxxxx |
| 39 | |
| 40 | # GitLab mirror |
| 41 | GITLAB_TOKEN=glpat-xxxxxxxxxxxx |
| 42 | ``` |
| 43 | |
| 44 | Per-repository mirror configuration is managed in the dashboard under **Repository Settings > Sync**. |
| 45 | |
| 46 | ## Sync Modes |
| 47 | |
| 48 | ### On-Demand |
| 49 | |
| 50 | Trigger a sync manually from the dashboard or CLI: |
| 51 | |
| 52 | ```bash |
| 53 | docker compose exec django python manage.py fossil_sync my-project |
| 54 | ``` |
| 55 | |
| 56 | ### Scheduled |
| 57 | |
| 58 | Configure a Celery Beat schedule to sync at regular intervals: |
| 59 | |
| 60 | ```python |
| 61 | # Runs every 15 minutes |
| 62 | CELERY_BEAT_SCHEDULE = { |
| 63 | 'sync-all-repos': { |
| 64 | 'task': 'fossil.tasks.sync_all', |
| 65 | 'schedule': 900.0, |
| 66 | }, |
| 67 | } |
| 68 | ``` |
| 69 | |
| 70 | ### Upstream Pull |
| 71 | |
| 72 | Pull updates from a remote Fossil server into your local instance: |
| 73 | |
| 74 | ```bash |
| 75 | docker compose exec django python manage.py fossil_pull my-project |
| 76 | ``` |
| 77 | |
| 78 | !!! warning "Direction matters" |
| 79 | The sync bridge is **one-way**: Fossil to Git. Changes pushed directly to a Git mirror will be overwritten on the next sync. Always push to the Fossil repo. |
| --- a/docs/getting-started/configuration.md | ||
| +++ b/docs/getting-started/configuration.md | ||
| @@ -0,0 +1,96 @@ | ||
| 1 | +# Configuration | |
| 2 | + | |
| 3 | +## Environment Variables | |
| 4 | + | |
| 5 | +All configuration is done through environment variables, loaded from `.env` in development. | |
| 6 | + | |
| 7 | +### Django Settings | |
| 8 | + | |
| 9 | +| Variable | Default | Description | | |
| 10 | +|---|---|---| | |
| 11 | +| `SECRET_KEY` | -- | Django secret key (required) | | |
| 12 | +| `DEBUG` | `False` | Enable debug mode | | |
| 13 | +| `ALLOWED_HOSTS` | `localhost` | Comma-separated list of allowed hosts | | |
| 14 | +| `TIME_ZONE` | `UTC` | Server timezone | | |
| 15 | + | |
| 16 | +### Database | |
| 17 | + | |
| 18 | +| Variable | Default | Description | | |
| 19 | +|---|---|---| | |
| 20 | +| `POSTGRES_DB` | `fossilrepo` | Database name | | |
| 21 | +| `POSTGRES_USER` | `fossilrepo` | Database user | | |
| 22 | +| `POSTGRES_PASSWORD` | -- | Database password (required) | | |
| 23 | +| `POSTGRES_HOST` | `postgres` | Database host | | |
| 24 | +| `POSTGRES_PORT` | `5432` | Database port | | |
| 25 | + | |
| 26 | +### Redis & Celery | |
| 27 | + | |
| 28 | +| Variable | Default | Description | | |
| 29 | +|---|---|---| | |
| 30 | +| `REDIS_URL` | `redis://redis:6379/0` | Redis connection URL | | |
| 31 | +| `CELERY_BROKER_URL` | `$REDIS_URL` | Celery broker (defaults to Redis URL) | | |
| 32 | + | |
| 33 | +### Fossil | |
| 34 | + | |
| 35 | +| Variable | Default | Description | | |
| 36 | +|---|---|---| | |
| 37 | +| `FOSSIL_REPO_DIR` | `/data/repos` | Directory where `.fossil` files are stored | | |
| 38 | +| `FOSSIL_BASE_URL` | -- | Base URL for Fossil web UI (e.g., `https://code.example.com`) | | |
| 39 | +| `FOSSIL_BINARY` | `fossil` | Path to the Fossil binary | | |
| 40 | + | |
| 41 | +### Caddy (Production) | |
| 42 | + | |
| 43 | +| Variable | Default | Description | | |
| 44 | +|---|---|---| | |
| 45 | +| `CADDY_DOMAIN` | -- | Your domain (e.g., `example.com`) | | |
| 46 | +| `CADDY_EMAIL` | -- | Email for Let's Encrypt certificates | | |
| 47 | + | |
| 48 | +### Litestream (Backups) | |
| 49 | + | |
| 50 | +| Variable | Default | Description | | |
| 51 | +|---|---|---| | |
| 52 | +| `LITESTREAM_ACCESS_KEY_ID` | -- | S3 access key | | |
| 53 | +| `LITESTREAM_SECRET_ACCESS_KEY` | -- | S3 secret key | | |
| 54 | +| `LITESTREAM_BUCKET` | -- | S3 bucket name | | |
| 55 | +| `LITESTREAM_ENDPOINT` | -- | S3 endpoint (for MinIO/B2) | | |
| 56 | +| `LITESTREAM_REGION` | `us-east-1` | S3 region | | |
| 57 | + | |
| 58 | +### Sync Bridge | |
| 59 | + | |
| 60 | +| Variable | Default | Description | | |
| 61 | +|---|---|---| | |
| 62 | +| `GITHUB_TOKEN` | -- | GitHub personal access token (for mirroring) | | |
| 63 | +| `GITLAB_TOKEN` | -- | GitLab personal access token (for mirroring) | | |
| 64 | + | |
| 65 | +## Caddy Configuration | |
| 66 | + | |
| 67 | +The Caddyfile controls SSL termination and subdomain routing. Each Fossil repo gets its own subdomain: | |
| 68 | + | |
| 69 | +``` | |
| 70 | +{$CADDY_DOMAIN} { | |
| 71 | + reverse_proxy django:8000 | |
| 72 | +} | |
| 73 | + | |
| 74 | +*.{$CADDY_DOMAIN} { | |
| 75 | + reverse_proxy fossil:8080 | |
| 76 | +} | |
| 77 | +``` | |
| 78 | + | |
| 79 | +Caddy automatically provisions Let's Encrypt certificates for all subdomains. | |
| 80 | + | |
| 81 | +## Litestream Configuration | |
| 82 | + | |
| 83 | +Litestream continuously replicates every `.fossil` SQLite file to S3: | |
| 84 | + | |
| 85 | +```yaml | |
| 86 | +dbs: | |
| 87 | + - path: /data/repos/*.fossil | |
| 88 | + replicas: | |
| 89 | + - type: s3 | |
| 90 | + bucket: ${LITESTREAM_BUCKET} | |
| 91 | + endpoint: ${LITESTREAM_ENDPOINT} | |
| 92 | + region: ${LITESTREAM_REGION} | |
| 93 | +``` | |
| 94 | + | |
| 95 | +!!! tip "Point-in-time recovery" | |
| 96 | + Litestream replicates WAL frames continuously. You can restore any `.fossil` file to any point in time, not just the latest snapshot. |
| --- a/docs/getting-started/configuration.md | |
| +++ b/docs/getting-started/configuration.md | |
| @@ -0,0 +1,96 @@ | |
| --- a/docs/getting-started/configuration.md | |
| +++ b/docs/getting-started/configuration.md | |
| @@ -0,0 +1,96 @@ | |
| 1 | # Configuration |
| 2 | |
| 3 | ## Environment Variables |
| 4 | |
| 5 | All configuration is done through environment variables, loaded from `.env` in development. |
| 6 | |
| 7 | ### Django Settings |
| 8 | |
| 9 | | Variable | Default | Description | |
| 10 | |---|---|---| |
| 11 | | `SECRET_KEY` | -- | Django secret key (required) | |
| 12 | | `DEBUG` | `False` | Enable debug mode | |
| 13 | | `ALLOWED_HOSTS` | `localhost` | Comma-separated list of allowed hosts | |
| 14 | | `TIME_ZONE` | `UTC` | Server timezone | |
| 15 | |
| 16 | ### Database |
| 17 | |
| 18 | | Variable | Default | Description | |
| 19 | |---|---|---| |
| 20 | | `POSTGRES_DB` | `fossilrepo` | Database name | |
| 21 | | `POSTGRES_USER` | `fossilrepo` | Database user | |
| 22 | | `POSTGRES_PASSWORD` | -- | Database password (required) | |
| 23 | | `POSTGRES_HOST` | `postgres` | Database host | |
| 24 | | `POSTGRES_PORT` | `5432` | Database port | |
| 25 | |
| 26 | ### Redis & Celery |
| 27 | |
| 28 | | Variable | Default | Description | |
| 29 | |---|---|---| |
| 30 | | `REDIS_URL` | `redis://redis:6379/0` | Redis connection URL | |
| 31 | | `CELERY_BROKER_URL` | `$REDIS_URL` | Celery broker (defaults to Redis URL) | |
| 32 | |
| 33 | ### Fossil |
| 34 | |
| 35 | | Variable | Default | Description | |
| 36 | |---|---|---| |
| 37 | | `FOSSIL_REPO_DIR` | `/data/repos` | Directory where `.fossil` files are stored | |
| 38 | | `FOSSIL_BASE_URL` | -- | Base URL for Fossil web UI (e.g., `https://code.example.com`) | |
| 39 | | `FOSSIL_BINARY` | `fossil` | Path to the Fossil binary | |
| 40 | |
| 41 | ### Caddy (Production) |
| 42 | |
| 43 | | Variable | Default | Description | |
| 44 | |---|---|---| |
| 45 | | `CADDY_DOMAIN` | -- | Your domain (e.g., `example.com`) | |
| 46 | | `CADDY_EMAIL` | -- | Email for Let's Encrypt certificates | |
| 47 | |
| 48 | ### Litestream (Backups) |
| 49 | |
| 50 | | Variable | Default | Description | |
| 51 | |---|---|---| |
| 52 | | `LITESTREAM_ACCESS_KEY_ID` | -- | S3 access key | |
| 53 | | `LITESTREAM_SECRET_ACCESS_KEY` | -- | S3 secret key | |
| 54 | | `LITESTREAM_BUCKET` | -- | S3 bucket name | |
| 55 | | `LITESTREAM_ENDPOINT` | -- | S3 endpoint (for MinIO/B2) | |
| 56 | | `LITESTREAM_REGION` | `us-east-1` | S3 region | |
| 57 | |
| 58 | ### Sync Bridge |
| 59 | |
| 60 | | Variable | Default | Description | |
| 61 | |---|---|---| |
| 62 | | `GITHUB_TOKEN` | -- | GitHub personal access token (for mirroring) | |
| 63 | | `GITLAB_TOKEN` | -- | GitLab personal access token (for mirroring) | |
| 64 | |
| 65 | ## Caddy Configuration |
| 66 | |
| 67 | The Caddyfile controls SSL termination and subdomain routing. Each Fossil repo gets its own subdomain: |
| 68 | |
| 69 | ``` |
| 70 | {$CADDY_DOMAIN} { |
| 71 | reverse_proxy django:8000 |
| 72 | } |
| 73 | |
| 74 | *.{$CADDY_DOMAIN} { |
| 75 | reverse_proxy fossil:8080 |
| 76 | } |
| 77 | ``` |
| 78 | |
| 79 | Caddy automatically provisions Let's Encrypt certificates for all subdomains. |
| 80 | |
| 81 | ## Litestream Configuration |
| 82 | |
| 83 | Litestream continuously replicates every `.fossil` SQLite file to S3: |
| 84 | |
| 85 | ```yaml |
| 86 | dbs: |
| 87 | - path: /data/repos/*.fossil |
| 88 | replicas: |
| 89 | - type: s3 |
| 90 | bucket: ${LITESTREAM_BUCKET} |
| 91 | endpoint: ${LITESTREAM_ENDPOINT} |
| 92 | region: ${LITESTREAM_REGION} |
| 93 | ``` |
| 94 | |
| 95 | !!! tip "Point-in-time recovery" |
| 96 | Litestream replicates WAL frames continuously. You can restore any `.fossil` file to any point in time, not just the latest snapshot. |
| --- a/docs/getting-started/first-repo.md | ||
| +++ b/docs/getting-started/first-repo.md | ||
| @@ -0,0 +1,75 @@ | ||
| 1 | +# Creating Your First Repository | |
| 2 | + | |
| 3 | +Once fossilrepo is running, you can create your first Fossil repository. | |
| 4 | + | |
| 5 | +## Via the Dashboard | |
| 6 | + | |
| 7 | +1. Log in at `http://localhost:8000` | |
| 8 | +2. Navigate to **Repositories** in the sidebar | |
| 9 | +3. Click **Create Repository** | |
| 10 | +4. Enter a name (e.g., `my-project`) | |
| 11 | +5. Click **Create** | |
| 12 | + | |
| 13 | +The repository is immediately available at `my-project.your-domain.com` (production) or through the local Fossil server (development). | |
| 14 | + | |
| 15 | +## Via the CLI | |
| 16 | + | |
| 17 | +```bash | |
| 18 | +# Inside the fossilrepo container | |
| 19 | +docker compose exec django python manage.py fossil_create my-project | |
| 20 | +``` | |
| 21 | + | |
| 22 | +This runs `fossil init`, registers the repo in the database, and (in production) Caddy automatically routes the subdomain. | |
| 23 | + | |
| 24 | +## What Happens Under the Hood | |
| 25 | + | |
| 26 | +```mermaid | |
| 27 | +sequenceDiagram | |
| 28 | + participant User | |
| 29 | + participant Django | |
| 30 | + participant Fossil | |
| 31 | + participant Litestream | |
| 32 | + participant S3 | |
| 33 | + | |
| 34 | + User->>Django: Create repo "my-project" | |
| 35 | + Django->>Fossil: fossil init /data/repos/my-project.fossil | |
| 36 | + Fossil-->>Django: Repository created | |
| 37 | + Django->>Django: Register in database | |
| 38 | + Litestream->>S3: Begin replicating my-project.fossil | |
| 39 | + Django-->>User: Repository ready | |
| 40 | +``` | |
| 41 | + | |
| 42 | +## Accessing Your Repository | |
| 43 | + | |
| 44 | +### Web UI | |
| 45 | + | |
| 46 | +Fossil includes a built-in web interface with: | |
| 47 | + | |
| 48 | +- **Timeline** -- commit history with diffs | |
| 49 | +- **Tickets** -- issue tracker | |
| 50 | +- **Wiki** -- project documentation | |
| 51 | +- **Forum** -- discussions | |
| 52 | + | |
| 53 | +### Clone via Fossil | |
| 54 | + | |
| 55 | +```bash | |
| 56 | +fossil clone https://my-project.your-domain.com my-project.fossil | |
| 57 | +fossil open my-project.fossil | |
| 58 | +``` | |
| 59 | + | |
| 60 | +### Clone via Git (Mirror) | |
| 61 | + | |
| 62 | +If you've configured the sync bridge: | |
| 63 | + | |
| 64 | +```bash | |
| 65 | +git clone https://github.com/your-org/my-project.git | |
| 66 | +``` | |
| 67 | + | |
| 68 | +!!! warning "Read-only mirror" | |
| 69 | + Git mirrors are downstream copies. Push changes to the Fossil repo -- they'll sync to Git automatically. | |
| 70 | + | |
| 71 | +## Next Steps | |
| 72 | + | |
| 73 | +- [Configure the sync bridge](../architecture/sync-bridge.md) to mirror to GitHub/GitLab | |
| 74 | +- [Set up backups](configuration.md#litestream-backups) with Litestream | |
| 75 | +- Explore the [architecture overview](../architecture/overview.md) |
| --- a/docs/getting-started/first-repo.md | |
| +++ b/docs/getting-started/first-repo.md | |
| @@ -0,0 +1,75 @@ | |
| --- a/docs/getting-started/first-repo.md | |
| +++ b/docs/getting-started/first-repo.md | |
| @@ -0,0 +1,75 @@ | |
| 1 | # Creating Your First Repository |
| 2 | |
| 3 | Once fossilrepo is running, you can create your first Fossil repository. |
| 4 | |
| 5 | ## Via the Dashboard |
| 6 | |
| 7 | 1. Log in at `http://localhost:8000` |
| 8 | 2. Navigate to **Repositories** in the sidebar |
| 9 | 3. Click **Create Repository** |
| 10 | 4. Enter a name (e.g., `my-project`) |
| 11 | 5. Click **Create** |
| 12 | |
| 13 | The repository is immediately available at `my-project.your-domain.com` (production) or through the local Fossil server (development). |
| 14 | |
| 15 | ## Via the CLI |
| 16 | |
| 17 | ```bash |
| 18 | # Inside the fossilrepo container |
| 19 | docker compose exec django python manage.py fossil_create my-project |
| 20 | ``` |
| 21 | |
| 22 | This runs `fossil init`, registers the repo in the database, and (in production) Caddy automatically routes the subdomain. |
| 23 | |
| 24 | ## What Happens Under the Hood |
| 25 | |
| 26 | ```mermaid |
| 27 | sequenceDiagram |
| 28 | participant User |
| 29 | participant Django |
| 30 | participant Fossil |
| 31 | participant Litestream |
| 32 | participant S3 |
| 33 | |
| 34 | User->>Django: Create repo "my-project" |
| 35 | Django->>Fossil: fossil init /data/repos/my-project.fossil |
| 36 | Fossil-->>Django: Repository created |
| 37 | Django->>Django: Register in database |
| 38 | Litestream->>S3: Begin replicating my-project.fossil |
| 39 | Django-->>User: Repository ready |
| 40 | ``` |
| 41 | |
| 42 | ## Accessing Your Repository |
| 43 | |
| 44 | ### Web UI |
| 45 | |
| 46 | Fossil includes a built-in web interface with: |
| 47 | |
| 48 | - **Timeline** -- commit history with diffs |
| 49 | - **Tickets** -- issue tracker |
| 50 | - **Wiki** -- project documentation |
| 51 | - **Forum** -- discussions |
| 52 | |
| 53 | ### Clone via Fossil |
| 54 | |
| 55 | ```bash |
| 56 | fossil clone https://my-project.your-domain.com my-project.fossil |
| 57 | fossil open my-project.fossil |
| 58 | ``` |
| 59 | |
| 60 | ### Clone via Git (Mirror) |
| 61 | |
| 62 | If you've configured the sync bridge: |
| 63 | |
| 64 | ```bash |
| 65 | git clone https://github.com/your-org/my-project.git |
| 66 | ``` |
| 67 | |
| 68 | !!! warning "Read-only mirror" |
| 69 | Git mirrors are downstream copies. Push changes to the Fossil repo -- they'll sync to Git automatically. |
| 70 | |
| 71 | ## Next Steps |
| 72 | |
| 73 | - [Configure the sync bridge](../architecture/sync-bridge.md) to mirror to GitHub/GitLab |
| 74 | - [Set up backups](configuration.md#litestream-backups) with Litestream |
| 75 | - Explore the [architecture overview](../architecture/overview.md) |
| --- a/docs/getting-started/installation.md | ||
| +++ b/docs/getting-started/installation.md | ||
| @@ -0,0 +1,115 @@ | ||
| 1 | +# Installation | |
| 2 | + | |
| 3 | +## Clone the Repository | |
| 4 | + | |
| 5 | +```bash | |
| 6 | +git clone https://github.com/ConflictHQ/fossilrepo.git | |
| 7 | +cd fossilrepo | |
| 8 | +``` | |
| 9 | + | |
| 10 | +## Environment Configuration | |
| 11 | + | |
| 12 | +Copy the example environment file and configure it: | |
| 13 | + | |
| 14 | +```bash | |
| 15 | +cp .env.example .env | |
| 16 | +``` | |
| 17 | + | |
| 18 | +Edit `.env` with your settings: | |
| 19 | + | |
| 20 | +```ini | |
| 21 | +# Django | |
| 22 | +SECRET_KEY=your-secret-key-here | |
| 23 | +DEBUG=True | |
| 24 | +ALLOWED_HOSTS=localhost,127.0.0.1 | |
| 25 | + | |
| 26 | +# Database | |
| 27 | +POSTGRES_DB=fossilrepo | |
| 28 | +POSTGRES_USER=fossilrepo | |
| 29 | +POSTGRES_PASSWORD=your-db-password | |
| 30 | + | |
| 31 | +# Redis | |
| 32 | +REDIS_URL=redis://redis:6379/0 | |
| 33 | + | |
| 34 | +# Fossil | |
| 35 | +FOSSIL_REPO_DIR=/data/repos | |
| 36 | +FOSSIL_BASE_URL=https://your-domain.com | |
| 37 | +``` | |
| 38 | + | |
| 39 | +## Start the Stack | |
| 40 | + | |
| 41 | +### Development | |
| 42 | + | |
| 43 | +```bash | |
| 44 | +# Build and start all services | |
| 45 | +make build | |
| 46 | + | |
| 47 | +# Run database migrations | |
| 48 | +make migrate | |
| 49 | + | |
| 50 | +# Create an admin user | |
| 51 | +make superuser | |
| 52 | + | |
| 53 | +# Load sample data (optional) | |
| 54 | +make seed | |
| 55 | +``` | |
| 56 | + | |
| 57 | +The development stack includes: | |
| 58 | + | |
| 59 | +- Django dev server on `http://localhost:8000` | |
| 60 | +- PostgreSQL 16 | |
| 61 | +- Redis | |
| 62 | +- Celery worker + beat | |
| 63 | +- Mailpit on `http://localhost:8025` | |
| 64 | + | |
| 65 | +### Production | |
| 66 | + | |
| 67 | +For production, you'll also configure Caddy and Litestream: | |
| 68 | + | |
| 69 | +```bash | |
| 70 | +# Copy production configs | |
| 71 | +cp docker/Caddyfile.example docker/Caddyfile | |
| 72 | +cp docker/litestream.yml.example docker/litestream.yml | |
| 73 | + | |
| 74 | +# Edit with your domain and S3 credentials | |
| 75 | +# Then start with the production compose file | |
| 76 | +docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d | |
| 77 | +``` | |
| 78 | + | |
| 79 | +## Verify Installation | |
| 80 | + | |
| 81 | +```bash | |
| 82 | +# Check all services are running | |
| 83 | +docker compose ps | |
| 84 | + | |
| 85 | +# Hit the health endpoint | |
| 86 | +curl http://localhost:8000/health/ | |
| 87 | + | |
| 88 | +# Open the dashboard | |
| 89 | +open http://localhost:8000 | |
| 90 | +``` | |
| 91 | + | |
| 92 | +!!! success "You should see" | |
| 93 | + The fossilrepo dashboard with navigation, login page, and (after seeding) sample repositories. | |
| 94 | + | |
| 95 | +## Common Issues | |
| 96 | + | |
| 97 | +??? question "Port 8000 already in use" | |
| 98 | + Change the Django port mapping in `docker-compose.yml`: | |
| 99 | + ```yaml | |
| 100 | + ports: | |
| 101 | + - "8001:8000" | |
| 102 | + ``` | |
| 103 | + | |
| 104 | +??? question "Database connection refused" | |
| 105 | + Ensure PostgreSQL has started before Django: | |
| 106 | + ```bash | |
| 107 | + docker compose logs postgres | |
| 108 | + ``` | |
| 109 | + The Django container waits for Postgres to be ready, but network issues on some Docker Desktop versions can cause timeouts. Restart with `make down && make up`. | |
| 110 | + | |
| 111 | +??? question "Permission denied on /data/repos" | |
| 112 | + The Fossil repo directory needs to be writable by the container user: | |
| 113 | + ```bash | |
| 114 | + sudo chown -R 1000:1000 /data/repos | |
| 115 | + ``` |
| --- a/docs/getting-started/installation.md | |
| +++ b/docs/getting-started/installation.md | |
| @@ -0,0 +1,115 @@ | |
| --- a/docs/getting-started/installation.md | |
| +++ b/docs/getting-started/installation.md | |
| @@ -0,0 +1,115 @@ | |
| 1 | # Installation |
| 2 | |
| 3 | ## Clone the Repository |
| 4 | |
| 5 | ```bash |
| 6 | git clone https://github.com/ConflictHQ/fossilrepo.git |
| 7 | cd fossilrepo |
| 8 | ``` |
| 9 | |
| 10 | ## Environment Configuration |
| 11 | |
| 12 | Copy the example environment file and configure it: |
| 13 | |
| 14 | ```bash |
| 15 | cp .env.example .env |
| 16 | ``` |
| 17 | |
| 18 | Edit `.env` with your settings: |
| 19 | |
| 20 | ```ini |
| 21 | # Django |
| 22 | SECRET_KEY=your-secret-key-here |
| 23 | DEBUG=True |
| 24 | ALLOWED_HOSTS=localhost,127.0.0.1 |
| 25 | |
| 26 | # Database |
| 27 | POSTGRES_DB=fossilrepo |
| 28 | POSTGRES_USER=fossilrepo |
| 29 | POSTGRES_PASSWORD=your-db-password |
| 30 | |
| 31 | # Redis |
| 32 | REDIS_URL=redis://redis:6379/0 |
| 33 | |
| 34 | # Fossil |
| 35 | FOSSIL_REPO_DIR=/data/repos |
| 36 | FOSSIL_BASE_URL=https://your-domain.com |
| 37 | ``` |
| 38 | |
| 39 | ## Start the Stack |
| 40 | |
| 41 | ### Development |
| 42 | |
| 43 | ```bash |
| 44 | # Build and start all services |
| 45 | make build |
| 46 | |
| 47 | # Run database migrations |
| 48 | make migrate |
| 49 | |
| 50 | # Create an admin user |
| 51 | make superuser |
| 52 | |
| 53 | # Load sample data (optional) |
| 54 | make seed |
| 55 | ``` |
| 56 | |
| 57 | The development stack includes: |
| 58 | |
| 59 | - Django dev server on `http://localhost:8000` |
| 60 | - PostgreSQL 16 |
| 61 | - Redis |
| 62 | - Celery worker + beat |
| 63 | - Mailpit on `http://localhost:8025` |
| 64 | |
| 65 | ### Production |
| 66 | |
| 67 | For production, you'll also configure Caddy and Litestream: |
| 68 | |
| 69 | ```bash |
| 70 | # Copy production configs |
| 71 | cp docker/Caddyfile.example docker/Caddyfile |
| 72 | cp docker/litestream.yml.example docker/litestream.yml |
| 73 | |
| 74 | # Edit with your domain and S3 credentials |
| 75 | # Then start with the production compose file |
| 76 | docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d |
| 77 | ``` |
| 78 | |
| 79 | ## Verify Installation |
| 80 | |
| 81 | ```bash |
| 82 | # Check all services are running |
| 83 | docker compose ps |
| 84 | |
| 85 | # Hit the health endpoint |
| 86 | curl http://localhost:8000/health/ |
| 87 | |
| 88 | # Open the dashboard |
| 89 | open http://localhost:8000 |
| 90 | ``` |
| 91 | |
| 92 | !!! success "You should see" |
| 93 | The fossilrepo dashboard with navigation, login page, and (after seeding) sample repositories. |
| 94 | |
| 95 | ## Common Issues |
| 96 | |
| 97 | ??? question "Port 8000 already in use" |
| 98 | Change the Django port mapping in `docker-compose.yml`: |
| 99 | ```yaml |
| 100 | ports: |
| 101 | - "8001:8000" |
| 102 | ``` |
| 103 | |
| 104 | ??? question "Database connection refused" |
| 105 | Ensure PostgreSQL has started before Django: |
| 106 | ```bash |
| 107 | docker compose logs postgres |
| 108 | ``` |
| 109 | The Django container waits for Postgres to be ready, but network issues on some Docker Desktop versions can cause timeouts. Restart with `make down && make up`. |
| 110 | |
| 111 | ??? question "Permission denied on /data/repos" |
| 112 | The Fossil repo directory needs to be writable by the container user: |
| 113 | ```bash |
| 114 | sudo chown -R 1000:1000 /data/repos |
| 115 | ``` |
| --- a/docs/getting-started/prerequisites.md | ||
| +++ b/docs/getting-started/prerequisites.md | ||
| @@ -0,0 +1,81 @@ | ||
| 1 | +# Prerequisites | |
| 2 | + | |
| 3 | +Before installing fossilrepo, ensure your server meets these requirements. | |
| 4 | + | |
| 5 | +## System Requirements | |
| 6 | + | |
| 7 | +| Requirement | Minimum | | |
| 8 | +|---|---| | |
| 9 | +| **OS** | Linux (Ubuntu 22.04+, Debian 12+, RHEL 9+) or macOS 13+ | | |
| 10 | +| **CPU** | 1 vCPU | | |
| 11 | +| **RAM** | 1 GB | | |
| 12 | +| **Disk** | 10 GB (scales with repo count) | | |
| 13 | +| **Python** | 3.12+ | | |
| 14 | + | |
| 15 | +## Required Software | |
| 16 | + | |
| 17 | +### Docker & Docker Compose | |
| 18 | + | |
| 19 | +Fossilrepo runs its infrastructure stack via Docker Compose. | |
| 20 | + | |
| 21 | +=== "Ubuntu/Debian" | |
| 22 | + | |
| 23 | + ```bash | |
| 24 | + # Install Docker | |
| 25 | + curl -fsSL https://get.docker.com | sh | |
| 26 | + sudo usermod -aG docker $USER | |
| 27 | + | |
| 28 | + # Verify | |
| 29 | + docker compose version | |
| 30 | + ``` | |
| 31 | + | |
| 32 | +=== "macOS" | |
| 33 | + | |
| 34 | + ```bash | |
| 35 | + # Install Docker Desktop | |
| 36 | + brew install --cask docker | |
| 37 | + | |
| 38 | + # Verify | |
| 39 | + docker compose version | |
| 40 | + ``` | |
| 41 | + | |
| 42 | +### Git | |
| 43 | + | |
| 44 | +Required for the sync bridge (mirroring to GitHub/GitLab). | |
| 45 | + | |
| 46 | +```bash | |
| 47 | +git --version # 2.30+ | |
| 48 | +``` | |
| 49 | + | |
| 50 | +### Make | |
| 51 | + | |
| 52 | +Used for running common commands. | |
| 53 | + | |
| 54 | +```bash | |
| 55 | +make --version | |
| 56 | +``` | |
| 57 | + | |
| 58 | +## Optional: S3-Compatible Storage | |
| 59 | + | |
| 60 | +For continuous backups via Litestream, you need an S3-compatible bucket: | |
| 61 | + | |
| 62 | +- **AWS S3** | |
| 63 | +- **MinIO** (self-hosted) | |
| 64 | +- **Backblaze B2** | |
| 65 | +- **DigitalOcean Spaces** | |
| 66 | + | |
| 67 | +!!! info "Local development" | |
| 68 | + S3 is not required for local development. Litestream is disabled by default in the dev Docker Compose configuration. | |
| 69 | + | |
| 70 | +## Ports | |
| 71 | + | |
| 72 | +The following ports are used by the stack: | |
| 73 | + | |
| 74 | +| Port | Service | | |
| 75 | +|---|---| | |
| 76 | +| `8000` | Django (management UI) | | |
| 77 | +| `443` | Caddy (HTTPS, production) | | |
| 78 | +| `80` | Caddy (HTTP redirect, production) | | |
| 79 | +| `5432` | PostgreSQL | | |
| 80 | +| `6379` | Redis | | |
| 81 | +| `8025` | Mailpit (dev only) | |
| --- a/docs/getting-started/prerequisites.md | |
| +++ b/docs/getting-started/prerequisites.md | |
| @@ -0,0 +1,81 @@ | |
| --- a/docs/getting-started/prerequisites.md | |
| +++ b/docs/getting-started/prerequisites.md | |
| @@ -0,0 +1,81 @@ | |
| 1 | # Prerequisites |
| 2 | |
| 3 | Before installing fossilrepo, ensure your server meets these requirements. |
| 4 | |
| 5 | ## System Requirements |
| 6 | |
| 7 | | Requirement | Minimum | |
| 8 | |---|---| |
| 9 | | **OS** | Linux (Ubuntu 22.04+, Debian 12+, RHEL 9+) or macOS 13+ | |
| 10 | | **CPU** | 1 vCPU | |
| 11 | | **RAM** | 1 GB | |
| 12 | | **Disk** | 10 GB (scales with repo count) | |
| 13 | | **Python** | 3.12+ | |
| 14 | |
| 15 | ## Required Software |
| 16 | |
| 17 | ### Docker & Docker Compose |
| 18 | |
| 19 | Fossilrepo runs its infrastructure stack via Docker Compose. |
| 20 | |
| 21 | === "Ubuntu/Debian" |
| 22 | |
| 23 | ```bash |
| 24 | # Install Docker |
| 25 | curl -fsSL https://get.docker.com | sh |
| 26 | sudo usermod -aG docker $USER |
| 27 | |
| 28 | # Verify |
| 29 | docker compose version |
| 30 | ``` |
| 31 | |
| 32 | === "macOS" |
| 33 | |
| 34 | ```bash |
| 35 | # Install Docker Desktop |
| 36 | brew install --cask docker |
| 37 | |
| 38 | # Verify |
| 39 | docker compose version |
| 40 | ``` |
| 41 | |
| 42 | ### Git |
| 43 | |
| 44 | Required for the sync bridge (mirroring to GitHub/GitLab). |
| 45 | |
| 46 | ```bash |
| 47 | git --version # 2.30+ |
| 48 | ``` |
| 49 | |
| 50 | ### Make |
| 51 | |
| 52 | Used for running common commands. |
| 53 | |
| 54 | ```bash |
| 55 | make --version |
| 56 | ``` |
| 57 | |
| 58 | ## Optional: S3-Compatible Storage |
| 59 | |
| 60 | For continuous backups via Litestream, you need an S3-compatible bucket: |
| 61 | |
| 62 | - **AWS S3** |
| 63 | - **MinIO** (self-hosted) |
| 64 | - **Backblaze B2** |
| 65 | - **DigitalOcean Spaces** |
| 66 | |
| 67 | !!! info "Local development" |
| 68 | S3 is not required for local development. Litestream is disabled by default in the dev Docker Compose configuration. |
| 69 | |
| 70 | ## Ports |
| 71 | |
| 72 | The following ports are used by the stack: |
| 73 | |
| 74 | | Port | Service | |
| 75 | |---|---| |
| 76 | | `8000` | Django (management UI) | |
| 77 | | `443` | Caddy (HTTPS, production) | |
| 78 | | `80` | Caddy (HTTP redirect, production) | |
| 79 | | `5432` | PostgreSQL | |
| 80 | | `6379` | Redis | |
| 81 | | `8025` | Mailpit (dev only) | |
+63
| --- a/docs/index.md | ||
| +++ b/docs/index.md | ||
| @@ -0,0 +1,63 @@ | ||
| 1 | +# Fossilrepo | |
| 2 | + | |
| 3 | +**Self-hosted Fossil forge. One command, full-stack code hosting.** | |
| 4 | + | |
| 5 | +our](fossilrepo-tour.gif) | |
| 6 | + | |
| 7 | +Fossilrepo is an omnibus-style installer for a production Fossil SCM server. It packages Fossil, Caddy (SSL/routing), Litestream (S3 backups), and a Django management layer into a single deployable unit. | |
| 8 | + | |
| 9 | +Think GitLab Omnibus, but for Fossil. | |
| 10 | + | |
| 11 | +## Why Fossil? | |
| 12 | + | |
| 13 | +A Fossil repository is a single SQLite file containing the full VCS history, issue tracker, wiki, forum, and timeline. No external services. No rate limits. Portable -- hand the file to someone and they have everything. | |
| 14 | + | |
| 15 | +- **Single-file repos** -- each `.fossil` file is the entire project | |
| 16 | +- **Built-in everything** -- issues, wiki, forum, timeline, web UI | |
| 17 | +- **No API rate limits** -- ideal for CI agents and automation | |
| 18 | +- **Litestream replication** -- continuous backup to S3 for free | |
| 19 | + | |
| 20 | +## What You Get | |
| 21 | + | |
| 22 | +| Component | Role | | |
| 23 | +|---|---| | |
| 24 | +| **Fossil server** | Serves all repos from a single process | | |
| 25 | +| **Caddy** | SSL termination, subdomain-per-repo routing | | |
| 26 | +| **Litestream** | Continuous SQLite replication to S3/MinIO | | |
| 27 | +| **Django management UI** | Repository lifecycle, user management, dashboards | | |
| 28 | +| **Sync bridge** | Mirror Fossil repos to GitHub/GitLab (read-only) | | |
| 29 | +| **Celery workers** | Background sync, scheduled tasks | | |
| 30 | + | |
| 31 | +## Quick Start | |
| 32 | + | |
| 33 | +```bash | |
| 34 | +# Clone the repo | |
| 35 | +git clone https://github.com/ConflictHQ/fossilrepo.git | |
| 36 | +cd fossilrepo | |
| 37 | + | |
| 38 | +# Start the full stack | |
| 39 | +make build | |
| 40 | + | |
| 41 | +# Seed development data | |
| 42 | +make seed | |
| 43 | + | |
| 44 | +# Open the dashboard | |
| 45 | +open http://localhost:8000 | |
| 46 | +``` | |
| 47 | + | |
| 48 | +## Architecture | |
| 49 | + | |
| 50 | +``` | |
| 51 | +Caddy (SSL termination, routing, subdomain per repo) | |
| 52 | + +-- fossil server --repolist /data/repos/ | |
| 53 | + +-- /data/repos/ | |
| 54 | + |-- projecta.fossil | |
| 55 | + |-- projectb.fossil | |
| 56 | + +-- ... | |
| 57 | + | |
| 58 | +Litestream -> S3/MinIO (continuous replication, point-in-time recovery) | |
| 59 | +``` | |
| 60 | + | |
| 61 | +New project = `fossil init`. No restart, no config change. Litestream picks it up automatically. | |
| 62 | + | |
| 63 | +## Lic |
| --- a/docs/index.md | |
| +++ b/docs/index.md | |
| @@ -0,0 +1,63 @@ | |
| --- a/docs/index.md | |
| +++ b/docs/index.md | |
| @@ -0,0 +1,63 @@ | |
| 1 | # Fossilrepo |
| 2 | |
| 3 | **Self-hosted Fossil forge. One command, full-stack code hosting.** |
| 4 | |
| 5 | our](fossilrepo-tour.gif) |
| 6 | |
| 7 | Fossilrepo is an omnibus-style installer for a production Fossil SCM server. It packages Fossil, Caddy (SSL/routing), Litestream (S3 backups), and a Django management layer into a single deployable unit. |
| 8 | |
| 9 | Think GitLab Omnibus, but for Fossil. |
| 10 | |
| 11 | ## Why Fossil? |
| 12 | |
| 13 | A Fossil repository is a single SQLite file containing the full VCS history, issue tracker, wiki, forum, and timeline. No external services. No rate limits. Portable -- hand the file to someone and they have everything. |
| 14 | |
| 15 | - **Single-file repos** -- each `.fossil` file is the entire project |
| 16 | - **Built-in everything** -- issues, wiki, forum, timeline, web UI |
| 17 | - **No API rate limits** -- ideal for CI agents and automation |
| 18 | - **Litestream replication** -- continuous backup to S3 for free |
| 19 | |
| 20 | ## What You Get |
| 21 | |
| 22 | | Component | Role | |
| 23 | |---|---| |
| 24 | | **Fossil server** | Serves all repos from a single process | |
| 25 | | **Caddy** | SSL termination, subdomain-per-repo routing | |
| 26 | | **Litestream** | Continuous SQLite replication to S3/MinIO | |
| 27 | | **Django management UI** | Repository lifecycle, user management, dashboards | |
| 28 | | **Sync bridge** | Mirror Fossil repos to GitHub/GitLab (read-only) | |
| 29 | | **Celery workers** | Background sync, scheduled tasks | |
| 30 | |
| 31 | ## Quick Start |
| 32 | |
| 33 | ```bash |
| 34 | # Clone the repo |
| 35 | git clone https://github.com/ConflictHQ/fossilrepo.git |
| 36 | cd fossilrepo |
| 37 | |
| 38 | # Start the full stack |
| 39 | make build |
| 40 | |
| 41 | # Seed development data |
| 42 | make seed |
| 43 | |
| 44 | # Open the dashboard |
| 45 | open http://localhost:8000 |
| 46 | ``` |
| 47 | |
| 48 | ## Architecture |
| 49 | |
| 50 | ``` |
| 51 | Caddy (SSL termination, routing, subdomain per repo) |
| 52 | +-- fossil server --repolist /data/repos/ |
| 53 | +-- /data/repos/ |
| 54 | |-- projecta.fossil |
| 55 | |-- projectb.fossil |
| 56 | +-- ... |
| 57 | |
| 58 | Litestream -> S3/MinIO (continuous replication, point-in-time recovery) |
| 59 | ``` |
| 60 | |
| 61 | New project = `fossil init`. No restart, no config change. Litestream picks it up automatically. |
| 62 | |
| 63 | ## Lic |
+84
| --- a/mkdocs.yml | ||
| +++ b/mkdocs.yml | ||
| @@ -0,0 +1,84 @@ | ||
| 1 | +site_name: Fossilrepo | |
| 2 | +site_url: https://fossilrepo.dev | |
| 3 | +site_description: Self-hosted Fossil forge -- omnibus installer for production Fossil SCM hosting | |
| 4 | +site_author: CONFLICT LLC | |
| 5 | +repo_url: https://github.com/ConflictHQ/fossilrepo | |
| 6 | +repo_name: ConflictHQ/fossilrepo | |
| 7 | + | |
| 8 | +theme: | |
| 9 | + name: material | |
| 10 | + _name: Fossilrepo | |
| 11 | +site_url: https://fossilrepo.dev | |
| 12 | +site_description: Self-hosted Fossil forge -- omnibus installer for production Fossil SCM hosting | |
| 13 | +site_author: CONFLICT LLC | |
| 14 | +repo_url: https://github.com/ConflictHQ/fossilrepo | |
| 15 | +repo_name: ConflictHQ/fossilrepo | |
| 16 | + | |
| 17 | +theme: | |
| 18 | + name: material | |
| 19 | + custom_dir: docs/overrides | |
| 20 | + logo: assets/images/conflict-logo.svg | |
| 21 | + favicon: assets/images/favicon.png | |
| 22 | + font: | |
| 23 | + text: Roboto | |
| 24 | + code: Roboto Mono | |
| 25 | + palette: | |
| 26 | + - media: "(prefers-color-scheme: dark)" | |
| 27 | + scheme: slate | |
| 28 | + primary: custom | |
| 29 | + accent: custom | |
| 30 | + toggle: | |
| 31 | + icon: material/brightness-4 | |
| 32 | + name: Switch to light mode | |
| 33 | + - media: "(prefers-color-scheme: light)" | |
| 34 | + scheme: default | |
| 35 | + primary: custom | |
| 36 | + accent: custom | |
| 37 | + toggle: | |
| 38 | + icon: material/brightness-7 | |
| 39 | + name: Switch to dark mode | |
| 40 | + features: | |
| 41 | + - navigation.instant | |
| 42 | + - navigation.tabs | |
| 43 | + - navigation.sections | |
| 44 | + - navigation.expand | |
| 45 | + - navigation.top | |
| 46 | + - search.suggest | |
| 47 | + - search.highlight | |
| 48 | + - content.code.copy | |
| 49 | + - content.tabs.link | |
| 50 | + - header.autohide | |
| 51 | + icon: | |
| 52 | + repo: fontawesome/brands/github | |
| 53 | + | |
| 54 | +extra_css: | |
| 55 | + - assets/css/custom.css | |
| 56 | + | |
| 57 | +plugins: | |
| 58 | + - search | |
| 59 | + | |
| 60 | +markdown_extensions: | |
| 61 | + - admonition | |
| 62 | + - pymdownx.details | |
| 63 | + - pymdownx.superfences: | |
| 64 | + custom_fences: | |
| 65 | + - name: mermaid | |
| 66 | + class: mermaid | |
| 67 | + format: !!python/name:pymdownx.superfences.fence_code_format | |
| 68 | + - pymdownx.tabbed: | |
| 69 | + alternate_style: true | |
| 70 | + - pymdownx.highlight: | |
| 71 | + anchor_linenums: true | |
| 72 | + - pymdownx.inlinehilite | |
| 73 | + - pymdownx.snippets | |
| 74 | + - attr_list | |
| 75 | + - md_in_html | |
| 76 | + - toc: | |
| 77 | + permalink: true | |
| 78 | + | |
| 79 | +nGetting Started: | |
| 80 | + - Prerequisites: getting-started/prerequisites.md | |
| 81 | + - Installation: getting-started/installation.md | |
| 82 | + - Configuration: getting-started/configuration.md | |
| 83 | + -site_name: Fossilrepo | |
| 84 | +site_ |
| --- a/mkdocs.yml | |
| +++ b/mkdocs.yml | |
| @@ -0,0 +1,84 @@ | |
| --- a/mkdocs.yml | |
| +++ b/mkdocs.yml | |
| @@ -0,0 +1,84 @@ | |
| 1 | site_name: Fossilrepo |
| 2 | site_url: https://fossilrepo.dev |
| 3 | site_description: Self-hosted Fossil forge -- omnibus installer for production Fossil SCM hosting |
| 4 | site_author: CONFLICT LLC |
| 5 | repo_url: https://github.com/ConflictHQ/fossilrepo |
| 6 | repo_name: ConflictHQ/fossilrepo |
| 7 | |
| 8 | theme: |
| 9 | name: material |
| 10 | _name: Fossilrepo |
| 11 | site_url: https://fossilrepo.dev |
| 12 | site_description: Self-hosted Fossil forge -- omnibus installer for production Fossil SCM hosting |
| 13 | site_author: CONFLICT LLC |
| 14 | repo_url: https://github.com/ConflictHQ/fossilrepo |
| 15 | repo_name: ConflictHQ/fossilrepo |
| 16 | |
| 17 | theme: |
| 18 | name: material |
| 19 | custom_dir: docs/overrides |
| 20 | logo: assets/images/conflict-logo.svg |
| 21 | favicon: assets/images/favicon.png |
| 22 | font: |
| 23 | text: Roboto |
| 24 | code: Roboto Mono |
| 25 | palette: |
| 26 | - media: "(prefers-color-scheme: dark)" |
| 27 | scheme: slate |
| 28 | primary: custom |
| 29 | accent: custom |
| 30 | toggle: |
| 31 | icon: material/brightness-4 |
| 32 | name: Switch to light mode |
| 33 | - media: "(prefers-color-scheme: light)" |
| 34 | scheme: default |
| 35 | primary: custom |
| 36 | accent: custom |
| 37 | toggle: |
| 38 | icon: material/brightness-7 |
| 39 | name: Switch to dark mode |
| 40 | features: |
| 41 | - navigation.instant |
| 42 | - navigation.tabs |
| 43 | - navigation.sections |
| 44 | - navigation.expand |
| 45 | - navigation.top |
| 46 | - search.suggest |
| 47 | - search.highlight |
| 48 | - content.code.copy |
| 49 | - content.tabs.link |
| 50 | - header.autohide |
| 51 | icon: |
| 52 | repo: fontawesome/brands/github |
| 53 | |
| 54 | extra_css: |
| 55 | - assets/css/custom.css |
| 56 | |
| 57 | plugins: |
| 58 | - search |
| 59 | |
| 60 | markdown_extensions: |
| 61 | - admonition |
| 62 | - pymdownx.details |
| 63 | - pymdownx.superfences: |
| 64 | custom_fences: |
| 65 | - name: mermaid |
| 66 | class: mermaid |
| 67 | format: !!python/name:pymdownx.superfences.fence_code_format |
| 68 | - pymdownx.tabbed: |
| 69 | alternate_style: true |
| 70 | - pymdownx.highlight: |
| 71 | anchor_linenums: true |
| 72 | - pymdownx.inlinehilite |
| 73 | - pymdownx.snippets |
| 74 | - attr_list |
| 75 | - md_in_html |
| 76 | - toc: |
| 77 | permalink: true |
| 78 | |
| 79 | nGetting Started: |
| 80 | - Prerequisites: getting-started/prerequisites.md |
| 81 | - Installation: getting-started/installation.md |
| 82 | - Configuration: getting-started/configuration.md |
| 83 | -site_name: Fossilrepo |
| 84 | site_ |