41 Commits

Author SHA1 Message Date
idk
5a20dc9121 disable windows forgejo builds 2025-05-09 17:40:28 +00:00
eyedeekay
e1985661aa update go version 2025-05-08 22:28:49 -04:00
eyedeekay
a89fc7a6a5 update go version 2025-05-08 22:17:17 -04:00
eyedeekay
36c21192f0 update go version 2025-05-08 22:15:33 -04:00
eyedeekay
cad60aac25 update go version 2025-05-08 22:09:55 -04:00
eyedeekay
283233c534 update go version 2025-05-08 20:17:29 -04:00
eyedeekay
fe561e9e99 add package-lock.json file? 2025-05-08 20:07:44 -04:00
eyedeekay
a25b108fe9 add node when building forgejo 2025-05-08 18:19:41 -04:00
eyedeekay
697ee54bef gitea should be the path name 2025-05-08 16:49:26 -04:00
eyedeekay
d81b6c906c try and build forgejo with the mod too 2025-05-08 16:32:31 -04:00
eyedeekay
960383c1c7 try and build forgejo with the mod too 2025-05-08 16:28:50 -04:00
eyedeekay
7713312fe3 try and build forgejo with the mod too 2025-05-08 16:24:46 -04:00
eyedeekay
7c354f9b52 try and build forgejo with the mod too 2025-05-08 16:18:31 -04:00
eyedeekay
4f9dcde18a align systemd unit with actual setup 2025-05-08 16:01:11 -04:00
eyedeekay
57ee6746ef Merge branch 'main' of github.com:go-i2p/go-gitlooseleaf 2025-05-08 15:59:18 -04:00
eyedeekay
3d31be0215 try and build forgejo with the mod too 2025-05-08 15:53:59 -04:00
idk
5e71999e5a Makefile 2025-05-08 05:16:20 +00:00
idk
54691e3cbe systemd stuff 2025-05-08 05:09:46 +00:00
eyedeekay
19025e2f10 Merge branch 'main' of github.com:go-i2p/go-gitlooseleaf 2025-05-05 15:48:53 -04:00
eyedeekay
2cc6f51329 update module 2025-05-05 15:48:01 -04:00
eyedeekay
a046854c58 Removed docker instructions which don't apply to looseleaf 2025-05-05 15:36:36 -04:00
idk
199ece6a13 remove docker stuff, update readme 2025-05-04 05:00:58 +00:00
eyedeekay
228ab09cf8 unset anonymity for this case 2025-05-01 18:10:07 -04:00
eyedeekay
fe0c790937 Use metadialer instead of reproducing code from elsewhere 2025-05-01 18:08:41 -04:00
eyedeekay
4f9ed824f5 add rate-limiter to external listeners 2025-05-01 18:03:10 -04:00
eyedeekay
b59cdadcde update modules and rebuild 2025-05-01 00:46:18 -04:00
eyedeekay
7c97f29d63 update modules and rebuild 2025-05-01 00:45:57 -04:00
eyedeekay
cb0ab3e597 update modules and rebuild 2025-05-01 00:08:24 -04:00
eyedeekay
d341180dbe adds install script 2025-04-29 23:51:43 -04:00
eyedeekay
1c5aeb87cd update meta-listener mirror.Listener to support multiple local listeners 2025-04-23 01:08:06 -04:00
eyedeekay
69d267bab5 update meta-listener mirror.Listener to support multiple local listeners 2025-04-23 00:36:54 -04:00
eyedeekay
f89e9dee28 update meta-listener mirror.Listener to support multiple local listeners 2025-04-23 00:21:41 -04:00
eyedeekay
1902034f2c update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 23:54:39 -04:00
eyedeekay
16b5f3b7c9 update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 23:36:00 -04:00
eyedeekay
aae3a5f571 update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 23:07:45 -04:00
eyedeekay
08e6728356 update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 22:49:54 -04:00
eyedeekay
6d90b7e40c update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 22:36:34 -04:00
eyedeekay
b669c9c6c2 update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 21:52:27 -04:00
eyedeekay
3daa81b6b1 update meta-listener mirror.Listener to support multiple local listeners 2025-04-22 21:12:19 -04:00
eyedeekay
4611687449 do a nightly with the new logging 2025-04-22 20:26:03 -04:00
eyedeekay
75d49f8d6f do a nightly with the new logging 2025-04-22 18:18:34 -04:00
17 changed files with 505 additions and 164 deletions

127
.github/workflows/forgejo-build.yml vendored Normal file
View File

@@ -0,0 +1,127 @@
name: Forgejo Build Pipeline
on:
push:
branches:
- main
schedule:
- cron: '0 0 * * *' # Runs daily at midnight UTC
workflow_dispatch: # Allow manual triggers
permissions:
contents: write # Required for creating releases
jobs:
check-release:
runs-on: ubuntu-latest
outputs:
new_tag: ${{ steps.get_latest_tag.outputs.tag }}
should_build: ${{ steps.check_existing.outputs.should_build }}
steps:
- name: Get Latest Forgejo Tag
id: get_latest_tag
run: |
LATEST_TAG=$(curl -s 'https://codeberg.org/api/v1/repos/forgejo/forgejo/releases?limit=1' | jq -r '.[0].tag_name')
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Latest Forgejo tag: $LATEST_TAG"
- name: Check Existing Release
id: check_existing
uses: actions/github-script@v7
with:
script: |
try {
const tag = '${{ steps.get_latest_tag.outputs.tag }}';
const release = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag: tag + '-forgejo'
});
core.setOutput('should_build', 'false');
} catch (error) {
core.setOutput('should_build', 'true');
}
build:
needs: check-release
if: needs.check-release.outputs.should_build == 'true'
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 120 # 2-hour timeout
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24.3'
cache: true
- name: Setup node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Checkout Forgejo Source
run: |
git clone https://codeberg.org/forgejo/forgejo.git forgejo-source
cd forgejo-source
git checkout ${{ needs.check-release.outputs.new_tag }}
- name: Build Forgejo
working-directory: forgejo-source
run: |
make clean
cp -v ../net_mirror.go modules/graceful/net_mirror.go
cp -v ../net_mirror_dialer.go modules/graceful/net_mirror_dialer.go
cp -v ../net_mirror_unix.go modules/graceful/net_mirror_unix.go
cp -v ../net_mirror_windows.go modules/graceful/net_mirror_windows.go
go mod tidy
make build
env:
TAGS: bindata sqlite sqlite_unlock_notify netgo osusergo
GOFLAGS: -ldflags="-extldflags=-static"
CO_ENABLED: 0
- name: Prepare Artifact
shell: bash
run: |
cd forgejo-source
ARTIFACT_NAME="gitea-${{ runner.os }}"
if [ "${{ runner.os }}" = "Windows" ]; then
mv gitea.exe "${ARTIFACT_NAME}.exe"
else
mv gitea "${ARTIFACT_NAME}"
fi
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: gitea-${{ runner.os }}
path: |
forgejo-source/gitea-${{ runner.os }}*
retention-days: 1
release:
needs: [check-release, build]
runs-on: ubuntu-latest
steps:
- name: Download All Artifacts
uses: actions/download-artifact@v4
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.check-release.outputs.new_tag }}-forgejo
name: "Forgejo ${{ needs.check-release.outputs.new_tag }}"
body: "Automated build of Forgejo ${{ needs.check-release.outputs.new_tag }}"
files: |
forgejo-Linux/*
forgejo-Windows/*
forgejo-macOS/*
draft: false
prerelease: false

97
.github/workflows/forgejo-nightly.yml vendored Normal file
View File

@@ -0,0 +1,97 @@
name: Forgejo Nightly Build
on:
push: # Run on any push
schedule:
- cron: '0 0 * * *' # Runs daily at midnight UTC
workflow_dispatch: # Allow manual triggers
permissions:
contents: write # Required for creating releases
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 120 # 2-hour timeout
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24.3'
cache: true
- name: Setup node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Checkout Forgejo Source
run: |
git clone https://codeberg.org/forgejo/forgejo.git forgejo-source
cd forgejo-source
git checkout forgejo
- name: Build Forgejo
working-directory: forgejo-source
run: |
make clean
cp -v ../net_mirror.go modules/graceful/net_mirror.go
cp -v ../net_mirror_dialer.go modules/graceful/net_mirror_dialer.go
cp -v ../net_mirror_unix.go modules/graceful/net_mirror_unix.go
cp -v ../net_mirror_windows.go modules/graceful/net_mirror_windows.go
go mod tidy
make build
env:
TAGS: bindata sqlite sqlite_unlock_notify netgo osusergo
GOFLAGS: -ldflags="-extldflags=-static"
CO_ENABLED: 0
- name: Prepare Artifact
shell: bash
run: |
cd forgejo-source
ARTIFACT_NAME="gitea-${{ runner.os }}"
if [ "${{ runner.os }}" = "Windows" ]; then
mv gitea.exe "${ARTIFACT_NAME}.exe"
else
mv gitea "${ARTIFACT_NAME}"
fi
- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: gitea-${{ runner.os }}
path: |
forgejo-source/gitea-${{ runner.os }}*
retention-days: 1
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download All Artifacts
uses: actions/download-artifact@v4
- name: Get Current Date
id: date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Create or Update Nightly Release
uses: ncipollo/release-action@v1
with:
tag: forgejo-nightly
name: "Forgejo Nightly Build (${{ steps.date.outputs.date }})"
body: "Automated nightly build of Forgejo from main branch, built on ${{ steps.date.outputs.date }}"
artifacts: "forgejo-Linux/*, forgejo-Windows/*, forgejo-macOS/*"
draft: false
prerelease: true
allowUpdates: true
removeArtifacts: false
replacesArtifacts: true

View File

@@ -61,7 +61,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: '1.24'
cache: true
- name: Checkout Gitea Source

View File

@@ -23,7 +23,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: '1.24'
cache: true
- name: Checkout Gitea Source

View File

@@ -1,17 +0,0 @@
Docker Instructions:
====================
The Dockerfile in this repo assumes a completely self-contained setup, where I2P resides in the same container as gitea.
This is purely for simplicity's sake.
In order to build it, use:
```sh
docker build -t go-i2p/go-gittisane .
```
then in order to run it, use:
```sh
docker run --name i2p-gittisane -d go-i2p/go-gittisane
docker log i2p-gittinsane
```

View File

@@ -1,34 +0,0 @@
# Stage 1: Download gittisane
FROM alpine:latest as downloader
RUN apk add --no-cache curl bash grep
WORKDIR /download/
COPY download.sh .
RUN /download/download.sh
RUN ls /download/downloads
RUN cp /download/downloads/gitea-Linux /download/gittisane-linux-amd64
# Stage 2: Runtime
FROM geti2p/i2p:latest
# Copy gittisane binary
COPY --from=downloader /download/gittisane-linux-amd64 /usr/local/bin/gittisane
RUN chmod +x /usr/local/bin/gittisane
# Create data directories
RUN mkdir -p /data/gitea
# Configure I2P for SAM
RUN echo "i2cp.tcp.host=127.0.0.1\n\
i2cp.tcp.port=7654\n\
sam.enabled=true\n\
sam.host=127.0.0.1\n\
sam.port=7656" >> /i2p/router.config
# Setup volumes
VOLUME ["/data/gitea", "/i2p/.i2p"]
WORKDIR /data/gitea
# Create startup script
COPY start.sh /usr/local/bin/start.sh
ENTRYPOINT ["start.sh"]

105
Makefile Normal file
View File

@@ -0,0 +1,105 @@
.PHONY: all download setup-user install-binary install-systemd enable disable uninstall clean help
# Installation paths
BINARY_PATH = /usr/local/bin/gitea
SYSTEMD_PATH = /etc/systemd/system
CONFIG_PATH = /etc/gitea
DATA_PATH = /var/lib/gitea
# Default target
all: help
help:
@echo "GitLooseLeaf - Modified Gitea with multi-protocol support"
@echo ""
@echo "Usage:"
@echo " make download - Download the latest gitea binary"
@echo " make setup-user - Create git user and required directories"
@echo " make install-binary - Install Gitea binary"
@echo " make install-systemd - Install systemd service files"
@echo " make enable - Enable and start Gitea service"
@echo " make disable - Disable and stop Gitea service"
@echo " make install - Complete installation (all above steps)"
@echo " make uninstall - Remove Gitea"
@echo " make clean - Clean up downloaded files"
@echo ""
@echo "Note: Many commands require root privileges (use sudo)"
# Download latest Gitea binary
download:
@echo "Downloading latest Gitea binary..."
mkdir -p downloads
GITEA_URL="https://github.com/go-i2p/go-gitlooseleaf/releases/download/nightly/gitea-Linux"; \
wget -O downloads/gitea "$$GITEA_URL" || curl -L -o downloads/gitea "$$GITEA_URL"
chmod +x downloads/gitea
# Setup git user and directories
setup-user:
@echo "Setting up git user and directories..."
id -u git &>/dev/null || adduser \
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
mkdir -p $(DATA_PATH)/{custom,data,log}
mkdir -p $(CONFIG_PATH)
chown -R git:git $(DATA_PATH)/
chmod -R 750 $(DATA_PATH)/
chown root:git $(CONFIG_PATH)
chmod 770 $(CONFIG_PATH)
# Install Gitea binary
install-binary: download
@echo "Installing Gitea binary..."
cp downloads/gitea $(BINARY_PATH)
chmod +x $(BINARY_PATH)
setcap CAP_NET_BIND_SERVICE=+eip $(BINARY_PATH)
# Install systemd service files
install-systemd:
@echo "Installing systemd service files..."
mkdir -p $(SYSTEMD_PATH)/gitea.service.d
cp etc/systemd/system/gitea.service $(SYSTEMD_PATH)/
cp etc/systemd/system/gitea.service.d/user-config.conf $(SYSTEMD_PATH)/gitea.service.d/
systemctl daemon-reload
# Enable and start Gitea service
enable:
@echo "Enabling and starting Gitea service..."
systemctl enable gitea.service
systemctl start gitea.service
@echo "Gitea service started successfully!"
@echo "Please configure your email in $(SYSTEMD_PATH)/gitea.service.d/user-config.conf"
@echo "Then restart with: systemctl restart gitea.service"
# Disable and stop Gitea service
disable:
@echo "Disabling and stopping Gitea service..."
systemctl disable gitea.service
systemctl stop gitea.service
# Complete installation
install: setup-user install-binary install-systemd enable
@echo "Installation complete!"
@echo "You can now access Gitea at:"
@echo "- HTTPS: https://$(shell hostname):3000"
@echo "- I2P/Tor: Check logs for actual addresses: journalctl -u gitea"
# Uninstall Gitea
uninstall: disable
@echo "Uninstalling Gitea..."
rm -f $(BINARY_PATH)
rm -f $(SYSTEMD_PATH)/gitea.service
rm -rf $(SYSTEMD_PATH)/gitea.service.d
systemctl daemon-reload
@echo "Gitea has been uninstalled."
@echo "Note: User and data directories were not removed."
@echo "To completely remove, delete: $(CONFIG_PATH) and $(DATA_PATH)"
# Clean up
clean:
@echo "Cleaning up..."
rm -rf downloads

129
README.md
View File

@@ -1,80 +1,87 @@
# go-gitlooseleaf
A soft-fork of gitea with support for running as a multi-protocol service. Just the mod and the CI files.
How it works:
=============
A soft-fork of Gitea that enables simultaneous multi-protocol access via standard TLS, I2P, and Tor onion services. This repository contains only the network interface modules and CI configuration needed to build custom Gitea binaries.
This uses GitHub CI to continuously build a version of Gitea that can simultaneously run as a regular TLS service, an I2P service, and a Tor onion service, based on the latest release of Gitea.
We can do this without requiring a patch to the Gitea source code.
This is because Gitea encapsulates its "Listening" and "Dialing" into functions, which can easily be substituted for alternative versions.
For instance, the network listener is set up by a function, `graceful.GetListener() (net.Listener, error)` in the file `modules/graceful/server.go`.
The default implementation of the `GetListener() (net.Listener, error)` function, `DefaultGetListener() (net.Listener, error)` is defined in the `modules/graceful/net_unix.go` for Unix-like systems and `modules/graceful/net_windows.go` for Windows-like systems.
A developer who wishes to "Mod" gitea to listen on another kind of connection do so by creating a new file which implements a `GetListener() (net.Listener, error)` function using alternate listener implementations.
## How It Works
On the client side, the same thing is possible because Go allows you to substitute the underlying transports used for the default HTTP Client.
So, in the absence of overriding settings, we can configure it to use TLS, SAMv3 (for I2P), and the Tor SOCKS proxy to build HTTP connections using the appropriate transport for each service.
This project leverages GitHub Actions to automatically build a modified version of Gitea that can simultaneously serve content over multiple protocols:
- Standard HTTPS/TLS connections
- I2P (Invisible Internet Project) network
- Tor onion services
Finally, if you need to include additional libraries, run `go mod tidy` in the root of the gitea checkout to include them.
The beauty of this approach is that it requires no changes to Gitea's core codebase, as Gitea intelligently encapsulates network operations through abstraction:
Here is a complete working example mod:
1. **Network Listeners**: Gitea uses `graceful.GetListener()` (defined in `modules/graceful/server.go`) for all incoming connections
2. **Network Clients**: Gitea's HTTP client connections can be configured with custom transport implementations
```Go
// copy this file to modules/graceful/net_multi.go before building gitea
package graceful
We take advantage of these abstractions by replacing the default implementations with our multi-protocol versions during the build process.
import (
"net"
"net/http"
## Implementation Details
"github.com/go-i2p/onramp"
"github.com/cretz/bine/tor"
)
The network listener replacement works because Gitea's default `GetListener()` implementations (`DefaultGetListener()`) are defined in platform-specific files:
- `modules/graceful/net_unix.go` for Unix-like systems
- `modules/graceful/net_windows.go` for Windows
// Set up the I2P Garlic API
var garlic, i2perr = onramp.NewGarlic("gitea-i2p", "127.0.0.1:7656", onramp.OPT_DEFAULTS)
Our implementation introduces a `MultiGetListener()` function that handles TLS, I2P, and Tor connections using the `go-meta-listener` package, while still supporting Unix sockets for internal functions.
// Set up the Tor onion service
var torInstance, torerr = tor.Start(nil, nil)
var onion, onionerr = torInstance.Listen(nil, 80)
Similarly, we replace the default HTTP client with a version that can route traffic through the appropriate network (TLS, I2P, or Tor) based on the destination.
// This implements the GetListener function for I2P. Note the exemption for Unix sockets.
## Current Implementation
The current implementation in `net_mirror.go` uses:
- `go-meta-listener/mirror` for listening on multiple protocols
- Rate limiting through `go-i2p/go-limit`
- Environment variables (`EMAIL`, `HOSTNAME`) for configuration
```go
// This implements the GetListener function for TLS, I2P, and Onion
func MultiGetListener(network, address string) (net.Listener, error) {
// Add a deferral to say that we've tried to grab a listener
defer GetManager().InformCleanup()
switch network {
case "unix", "unixpacket":
// I2P isn't really a replacement for the stuff you use Unix sockets for and it's also not an anonymity risk, so treat them normally
unixAddr, err := ResolveUnixAddr(network, address)
if err != nil {
return nil, err
}
return GetListenerUnixWrapper(network, unixAddr)
default:
return mirror.Listen("tcp", address, "./certs", true)
}
// Support for Unix sockets remains unchanged
if network == "unix" || network == "unixpacket" {
unixAddr, err := ResolveUnixAddr(network, address)
if err != nil {
return nil, err
}
return GetListenerUnixWrapper(network, unixAddr)
}
// For TCP connections, create a multi-protocol mirror listener
ml, err := mirrorListener.Listen(address, os.Getenv("EMAIL"), "./certs", true)
if err != nil {
return nil, err
}
// Apply rate limiting
return limitedlistener.NewLimitedListener(ml,
limitedlistener.WithMaxConnections(500), // concurrent connections
limitedlistener.WithRateLimit(24), // connections per second
), nil
}
// We use `init() to ensure that the appropriate Listeners and Dialers are correctly placed at runtime
func init() {
GetListener = MultiGetListener
/*Dialer not shown here*/
}
```
Caveats
-------
## Usage Caveats
Gitea makes a few other kinds of connections, besides `HTTP`, if instructed to do so in the config file.
For instance, there is an SMTP client.
Not all of these connections are automatically routed through the appropriate anonymity networks in this configuration.
For I2P, you might need to use `127.0.0.1:7659/7660` for SMTP. For Tor, you would configure SOCKS proxy settings.
Similarly, SSH client connections need additional configuration to properly route through these networks.
Additional adjustments to the configuration can be made to also route these services across the appropriate networks but aren't fully documented here at this time.
While the HTTP interface works seamlessly across all three protocols, other Gitea communication channels require additional configuration:
License
-------
1. **SMTP Client**: If configured, email connections from Gitea will need proper routing:
- For I2P: Use local ports like `127.0.0.1:7659/7660`
- For Tor: Configure appropriate SOCKS proxy settings
Both this mod and gitea are licensed under the MIT license.
See LICENSE for net_multi*.go in this repository.
LICENSE-gitea.md is a copy of the Gitea license from https://github.com/go-gitea/gitea
2. **SSH Connections**: Git operations over SSH require additional configuration to properly route through anonymity networks. These settings depend on your specific deployment environment.
3. **Environment Variables**:
- `EMAIL`: Used for TLS certificate generation (required for HTTPS)
- `HOSTNAME`: Server hostname (defaults to local machine name if not set)
## Installation
You can:
1. Download prebuilt binaries from the [releases page](https://github.com/go-i2p/go-gitlooseleaf/releases)
2. Use the included `install.sh` script to set up a system service
3. Build from source using the GitHub Actions workflows as a reference
## License
Both this modification and Gitea itself are licensed under the MIT license.
- See [LICENSE](LICENSE) for this project's license
- See [LICENSE-gitea.md](LICENSE-gitea.md) for the Gitea license from https://github.com/go-gitea/gitea

View File

@@ -0,0 +1,29 @@
[Unit]
Description=Gitea (Modified with multi-protocol TLS/I2P/Tor support)
Documentation=https://github.com/go-i2p/go-gitlooseleaf
After=network.target postgresql.service mysql.service mariadb.service
Wants=network.target
[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/home/git
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
RestartSec=10
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
# Hardening measures
ProtectSystem=full
PrivateTmp=true
PrivateDevices=true
NoNewPrivileges=true
ReadWritePaths=/var/lib/gitea /etc/gitea /home/git
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Load user-modifiable configuration from drop-in directory
# This will automatically include all .conf files in gitea.service.d/
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,22 @@
[Service]
# User-configurable environment variables for multi-protocol support
# Required for TLS certificate generation - CHANGE THIS!
Environment="EMAIL=your-email@example.com"
# Optional: Set explicit hostname (defaults to system hostname if not set)
# Environment="HOSTNAME=your-hostname"
# Optional: Performance tuning
# Environment="MAX_CONNECTIONS=500"
# Environment="RATE_LIMIT=24"
# Optional: Certificate directory
# Environment="CERT_DIR=/var/lib/gitea/certs"
# Optional: Additional environment variables for database, etc.
# Environment="GITEA_DATABASE_TYPE=postgres"
# Environment="GITEA_DATABASE_HOST=localhost:5432"
# Environment="GITEA_DATABASE_NAME=gitea"
# Environment="GITEA_DATABASE_USER=gitea"
# Environment="GITEA_DATABASE_PASSWD=gitea"

9
go.mod
View File

@@ -1,16 +1,18 @@
module github.com/go-i2p/go-gittisane
go 1.23.5
go 1.24.2
require (
github.com/go-i2p/go-meta-listener v0.0.0-20250419155249-feebe95fe95a
github.com/go-i2p/onramp v0.33.92
github.com/go-i2p/go-limit v0.0.0-20250203203118-210616857c15
github.com/go-i2p/go-meta-dialer v0.0.0-20250501024057-715e91be3cfe
github.com/go-i2p/go-meta-listener v0.0.4-0.20250505194551-6b30e62ee419
)
require (
github.com/cretz/bine v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/go-i2p/i2pkeys v0.33.10-0.20241113193422-e10de5e60708 // indirect
github.com/go-i2p/onramp v0.33.92 // indirect
github.com/go-i2p/sam3 v0.33.9 // indirect
github.com/opd-ai/wileedot v0.0.0-20241217172720-521d4175e624 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -21,4 +23,5 @@ require (
golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.9.0 // indirect
)

10
go.sum
View File

@@ -4,8 +4,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-i2p/go-meta-listener v0.0.0-20250419155249-feebe95fe95a h1:oKKNMSDp73q31UoAiFQD//xV4EeP70/TqsBzQAVKTAU=
github.com/go-i2p/go-meta-listener v0.0.0-20250419155249-feebe95fe95a/go.mod h1:wF/MCCfB40gZyT9WtuYWQkUOPrnoTzA+NG0zpsy3s4M=
github.com/go-i2p/go-limit v0.0.0-20250203203118-210616857c15 h1:ASjMbwlepoDQfrhv+H2B5ICBPJU5ES1JzmOxzPDx3YQ=
github.com/go-i2p/go-limit v0.0.0-20250203203118-210616857c15/go.mod h1:4jjmVRhvKj47sQ6B6wdDhN1IrEZunE6KwkYLQx/BeVE=
github.com/go-i2p/go-meta-dialer v0.0.0-20250501024057-715e91be3cfe h1:9Rxw2KtMCRKZHI4WavUAaatzKmc64V6kiYvcyTMHjeU=
github.com/go-i2p/go-meta-dialer v0.0.0-20250501024057-715e91be3cfe/go.mod h1:++xHSOvnGymRSyFbi9A9hztcfwKfU6/nJAtVxrNo8Zo=
github.com/go-i2p/go-meta-listener v0.0.4-0.20250505194551-6b30e62ee419 h1:zMq0nZ6wmJktnRwy1hFXzDTSKlZ4Cah2jdzvtp9tH2k=
github.com/go-i2p/go-meta-listener v0.0.4-0.20250505194551-6b30e62ee419/go.mod h1:wF/MCCfB40gZyT9WtuYWQkUOPrnoTzA+NG0zpsy3s4M=
github.com/go-i2p/i2pkeys v0.0.0-20241108200332-e4f5ccdff8c4/go.mod h1:m5TlHjPZrU5KbTd7Lr+I2rljyC6aJ88HdkeMQXV0U0E=
github.com/go-i2p/i2pkeys v0.33.10-0.20241113193422-e10de5e60708 h1:Tiy9IBwi21maNpK74yCdHursJJMkyH7w87tX1nXGWzg=
github.com/go-i2p/i2pkeys v0.33.10-0.20241113193422-e10de5e60708/go.mod h1:m5TlHjPZrU5KbTd7Lr+I2rljyC6aJ88HdkeMQXV0U0E=
@@ -44,6 +48,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

26
install.sh Normal file
View File

@@ -0,0 +1,26 @@
#! /usr/bin/env sh
# AS ROOT
adduser \
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea
killall gitea
sleep 3s
GITEA_URL=https://github.com/go-i2p/go-gitlooseleaf/releases/download/nightly/gitea-Linux
wget -O /usr/local/bin/gitea "$GITEA_URL"
chmod +x /usr/local/bin/gitea
setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/gitea
su - git

View File

@@ -9,6 +9,8 @@ import (
"os"
"github.com/go-i2p/go-meta-listener/mirror"
limitedlistener "github.com/go-i2p/go-limit"
)
func hostname() string {
@@ -51,8 +53,16 @@ func MultiGetListener(network, address string) (net.Listener, error) {
return nil, err
}
return GetListenerUnixWrapper(network, unixAddr)
default:
return mirrorListener.Listen(address, EMAIL, "./certs", true)
ml, err := mirrorListener.Listen(address, EMAIL, "./certs", true)
if err != nil {
return nil, err
}
return limitedlistener.NewLimitedListener(ml,
limitedlistener.WithMaxConnections(500), // max concurrent
limitedlistener.WithRateLimit(24), // per second
), nil
}
}

View File

@@ -2,43 +2,13 @@ package graceful
import (
"net"
"net/url"
"strings"
"github.com/go-i2p/onramp"
)
var (
Garlic, GarlicErr = onramp.NewGarlic("git-looseleaf", "127.0.0.1:7656", onramp.OPT_WIDE)
Onion, OnionErr = onramp.NewOnion("git-looseleaf")
metadialer "github.com/go-i2p/go-meta-dialer"
)
func Dial(network, addr string) (net.Conn, error) {
// convert the addr to a URL
url, err := url.Parse(addr)
if err != nil {
return nil, err
}
// get the domain name
domain := url.Hostname()
// get the top-level domain
fr := strings.Split(domain, ".")
tld := fr[len(fr)-1]
switch tld {
case "i2p":
if GarlicErr != nil {
return nil, GarlicErr
}
// I2P is a special case, we need to use the garlic dialer
return Garlic.Dial("i2p", addr)
case "onion":
if OnionErr != nil {
return nil, OnionErr
}
// Onion is a special case, we need to use the onion dialer
return Onion.Dial("onion", addr)
default:
// For everything else, we can use the default dialer
return net.Dial(network, addr)
if metadialer.ANON {
metadialer.ANON = false
}
return metadialer.Dial(network, addr)
}

0
package-lock.json generated Normal file
View File

View File

@@ -1,10 +0,0 @@
#! /bin/sh
nohup /startapp.sh 2> err.log 1> log.log &
export countdown=30
while [ countdown -gt 0 ]; do
echo "Waiting for app to start... $countdown seconds left"
countdown=$((countdown - 1))
sleep 1
done
ls /usr/local/bin
/usr/local/bin/gittisane web