# Frogue 🐸

Frogue is destined to be a [ForgeFed]-enabled software forge.

It doesn't have the all the blingy stuff [ForgeJo]/[Gitea] have, but it's pretty fast and low-cpu. It's also very alpha-stage software (did you know that the existence of alpha software stems in fact from observation of non-free software? Modern science postulates that free software doesn't exhibit the same behaviour, making the whole alpha software theory possibly moot).

There was once IronBridge, which was a pretty advanced unreleased ForgeFed project, but it became too messy and undocumented to really be viable. But then i still wanted to create a software forge for my own use. So i started Frogue as a rewrite with many copy-pasting from this earlier project. But then i thought that it would still be great to be able to use the forge with ForgeFed, so i started implementing the ForgeFed concepts on top of what i already did.

## Forge features

- [x] Host public/private git repositories;
- [x] Browse files;
- [x] SSH interface to push commits;
- [x] Show commits history;
- [x] Propose/Merge sets of changes (Patch Proposals);
- [x] Report bugs;
- [ ] Teams/groups;
- [ ] Permissions (current model: owner has all rights, logged-in users some rights, guest users no rights);
- [ ] Repository Activity feed;
- [ ] Notifications;
- [ ] Deploy keys;

### Out of scope

These are features that are not considered planned, either at the moment or ever.

- CI/CD (hooks are still planned so you can notify your favorite CI system)
- Releases: use tags.
- Pages: no web hosting.
- ???

## Federation status

So, it's still heavily a work in progress but when Federation support is enabled you:
- Have a fediverse handle (e.g., `@alice@forge.example.org`)
- Publish notes that appear in their followers' feeds
- Receive follows, likes, and announces from other ActivityPub-compatible platforms (same as above)
- Create and federate tickets across ForgeFed-compatible forges
- Submit patches (merge requests) via federation from remote repositories
- Federate ticket and patch discussions as ActivityPub conversations

You enable Federation by setting `FROGUE_PUBLIC_URL`. So in the previous example, `FROGUE_PUBLIC_URL=https://forge.example.org`.
Honestly i'm not sure what happens if you don't enable federation. I started without the idea of requiring Federation to use the forge but i've spent so much time re-implementing ForgeFed i'm not entirely sure it works without.

There's lots of tests but as everybody knows, even having 100% coverage doesn't guarantee anything.

### Current limitations

Mhhhhh phew that's kind of a hard one. Basically everything apart from the stuff specified ?
- `Repositories` and their `PatchTracker`/`IssueTracker` are kinda implemented
- No moderation: you can't block/silence/defederate users/instances for now
- mentions and stuff beyond basic Like/Announce are not yet supported
- ForgeFed & ActivityPub's integration tests work and AP successfully interacts in the real world but it's still a bit early. I have no doubt i'll see some really weird stuff.
- I'll make a more complete precise list of supported actors/activities later.

## Installation

For now, it's very roots:

1. Clone this repository; `cd` into it
2. run `make`. This will download the internet and produce a binary at `target/release/frogue`. It is heavily recommended you copy this binary to a "static" path: it should not change, as this path is also used by git hooks when receiving commits. Running `sudo make install` will put this binary at `/usr/local/bin/frogue`.
3. Run this binary with the appropriate envvars: See [lib.rs](frogue/src/lib.rs). One setup i'd recommend is running via systemd with a `Service` unit file that looks like this:
   ```ini
   # /etc/systemd/system/frogue.service
   [Unit]
   Description=Frogue ForgeFed server
   After=network-online.target
   Wants=network-online.target
   
   [Service]
   Type=exec
   # of course, you need to create the UNIX user
   User=git
   Group=git
   WorkingDirectory=/var/lib/frogue
   EnvironmentFile=/etc/frogue/frogue.env
   ExecStart=/usr/local/bin/frogue
   Restart=on-failure
   RestartSec=5
   
   # /var/lib/frogue, created and chowned to git: automatically.
   StateDirectory=frogue
   StateDirectoryMode=0750
   
   # Hardening
   NoNewPrivileges=yes
   PrivateTmp=yes
   ProtectSystem=strict
   ProtectHome=yes
   ProtectKernelTunables=yes
   ProtectKernelModules=yes
   ProtectControlGroups=yes
   RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
   RestrictNamespaces=yes
   RestrictRealtime=yes
   RestrictSUIDSGID=yes
   LockPersonality=yes
   MemoryDenyWriteExecute=yes
   
   [Install]
   WantedBy=multi-user.target
   ```

   `/etc/frogue/frogue.env` could look like this:
   ```sh
   # /etc/frogue/frogue.env
   # Federation / public identity
   FROGUE_PUBLIC_URL=https://forge.example.com
   
   # HTTP, localhost only; use nginx/certbot to terminate TLS connections
   FROGUE_BIND_ADDR=127.0.0.1:6565
   
   # SSH — bound directly, advertised as git@example.com:2222
   FROGUE_SSH_BIND_ADDR=0.0.0.0:2222
   FROGUE_SSH_HOST=example.com:2222
   FROGUE_SSH_USER=git
   FROGUE_SSH_HOST_KEY=/var/lib/frogue/ssh_host_ed25519_key
   
   # Storage
   FROGUE_REPO_ROOT=/var/lib/frogue/repos
   FROGUE_DATABASE_URL=sqlite:///var/lib/frogue/frogue.sqlite?mode=rwc
   
   # Generate once: openssl rand -hex 32
   # Without it, every restart invalidates all browser sessions.
   FROGUE_SESSION_SECRET=changemechangemechangemechangemechangemechangemechangeme
   
   # Invite-only registration
   FROGUE_REGISTRATION_MODE=invite_only
   # Optional tuning:
   #FROGUE_INVITES_VALIDITY_SECONDS=172800
   #FROGUE_INVITES_ALLOWED_PER_DAY=5
   
   # Telemetry that can be useful if you want to inspect traces. i use jaeger. no personal data saved.
   # OTEL_TRACES_EXPORTER=otlp
   # OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 # example if you use local jaeger
   # OTEL_SERVICE_NAME=frogue
   # OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production
   ```
4. check everything works. 

Configuration is done via envvar, you can view a list of them and their defaults in [the first lines of `frogue/src/lib.rs`](frogue/src/lib.rs).

As a side note: there's currently no way to proxy ssh connections.

## Contributing

Well, frankly, i need help. I'm no graphic designer, i have Chaotic Brain Syndrome (that's when oh a squirrel) and so there's probably lots of bugs and inconsistencies. I try to note them down in [TODO.md](TODO.md) when i notice them but sometimes i'm too into the zone to think of it, or i've seen it so many times already that i don't notice it anymore.

The code is a bit of a mess, but as `<pe>` on Libera.chat said: <q cite="ircs://pe@libera.chat/">You can always deslop your human slop later</q>. So i still publish it.

So. You can contribute by:
- Filing issue reports (if the issue filing is broken, you can also contact me on the Fediverse at [`@ololduck@vit.am`](https://vit.am/snac/ololduck)) or you can find me in the `#frogue` channel on Libera.Chat.
- You can contribute code! (Well, in theory. It's possible you can't contribute code because registrations are closed and that i haven't yet implemented ForgeFed's `Patch` support, or myriad of other reasons). This project especially needs a graphical identity/consistency, but every code contribution is welcome.
- Documentation! Docs are great and this early i don't have much. To be honest i'm not sure writing heavy docs is such a good idea at the moment since it's still very early.
- Just being interested a talking about this project, it's a great motivator!

## FAQ

<details class="faq-item">
    <summary>Why the name <em>Frogue</em>?</summary>
    <p>Because i like frogs 🐸, that "forge" and "frog" are similar and that the combination of a frog and the style of the <a href="https://en.wikipedia.org/wiki/Vogue_(magazine)">Vogue magazine</a> was hilarious to me at the time.</p>
    <p>As for why not 🦆 ducks, since i am also fond of them: it's simply because the duck emoji 🦆 is way less cute than the frog one 🐸.</p>
</details>

<details class="faq-item">
    <summary>Are LLMs ("AI") used in this project?</summary>
    <p><em><dfn title="Too Long, Didn't Read">TL;DR</dfn></em>: Yes they are.</p>
    <p>
        A local LLM (<code>llama3.2</code>, via <code>llama-cpp</code>) has been used for commits messages and many docstrings (<code>///</code> comments in Rust), as well as some comments. I'm not the most orderly of people and LLMs have helped me make a bit of sense in this chaotic brain of mine. Or at least help me remember stuff by putting it in context.
    </p>
    <p>
        I've long pondered the ethical and political considerations of LLMs, and i've come to the (admitedly self-indulgent) opinion that local LLM use of "small" models was "<em>kind of OK for natural language/descriptive stuff</em>". I've also pondered about energy consumption and did some math and realised that boiling the water for my morning coffee was still more expensive (as raw energy) than running <code>llama3.2</code> on my graphic card at home. So yeah, in the end, i rationalized that using LLMs to make this project more accessible both for myself and potential contributors was the right thing to do.
    </p>
    <p>
        That doesn't mean i don't wish for more ethical LLM creation and use or condone the current LLM ecosystem (capitalistic, neo-liberal society, really) as well as it doesn't solve the ecological considerations of widespread LLM use. Also, widespread public data use should produce public results.
    </p>
    <p>And if you (who am i kidding? you will) spot non-sensical/convoluted/weird code, that's my fault. Sorry. (Legal) Drugs have been involved.</p>
</details>

[ForgeFed]: https://forgefed.org/
[ForgeJo]: https://forgejo.org/
[Gitea]: https://gitea.com/
