Add forgejo (with shared postgres), docs/ideas; fix ENOTDIR in local catalog listing
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
161464602e
commit
d66db4e85e
7 changed files with 150 additions and 1 deletions
15
README.md
15
README.md
|
|
@ -20,6 +20,10 @@ homelab/
|
||||||
│ │ └── users_database.yml
|
│ │ └── users_database.yml
|
||||||
│ ├── lldap/ # lightweight LDAP user store
|
│ ├── lldap/ # lightweight LDAP user store
|
||||||
│ │ └── metadata.json
|
│ │ └── metadata.json
|
||||||
|
│ ├── postgres/ # shared PostgreSQL (database for Forgejo & future apps)
|
||||||
|
│ │ └── metadata.json
|
||||||
|
│ ├── forgejo/ # self-hosted Git (web + SSH), uses postgres
|
||||||
|
│ │ └── metadata.json
|
||||||
│ ├── multistreaming/ # self-built: OBS ingest -> multi-platform re-streaming
|
│ ├── multistreaming/ # self-built: OBS ingest -> multi-platform re-streaming
|
||||||
│ │ ├── metadata.json
|
│ │ ├── metadata.json
|
||||||
│ │ ├── Dockerfile
|
│ │ ├── Dockerfile
|
||||||
|
|
@ -65,6 +69,17 @@ for any future OIDC-capable app. Install order: `lldap`, `authelia`, `nginx-prox
|
||||||
bun run src/index.ts install lldap authelia nginx-proxy-manager
|
bun run src/index.ts install lldap authelia nginx-proxy-manager
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Git (Forgejo + PostgreSQL)
|
||||||
|
|
||||||
|
[`forgejo`](services/forgejo) is the self-hosted git server, backed by the shared [`postgres`](services/postgres)
|
||||||
|
service. Both join the `homelab` docker network; PostgreSQL publishes no host port (docker-internal only).
|
||||||
|
|
||||||
|
- Web UI: `http://10.0.0.5:3000` (LAN only) — first visit creates the admin account.
|
||||||
|
- Git over SSH: `ssh://git@10.0.0.5:2222/<owner>/<repo>.git` (container SSH on host port 2222; host sshd keeps port 22).
|
||||||
|
- Registration is disabled; users come through the identity stack (Authelia SSO) later.
|
||||||
|
- Install order: `postgres` first, then `forgejo` with `--env PG_PASSWORD=<value>` taken from `~/.homelab/services/postgres/.env`.
|
||||||
|
- Update `FORGEJO_ROOT_URL` / `FORGEJO_SSH_DOMAIN` to the public domain once NPM proxies `git.example.com`.
|
||||||
|
|
||||||
## Network & DMZ topology
|
## Network & DMZ topology
|
||||||
|
|
||||||
[`portainer`](services/portainer) is the Docker/network manager: from its dashboard you can create
|
[`portainer`](services/portainer) is the Docker/network manager: from its dashboard you can create
|
||||||
|
|
|
||||||
11
docs/ideas.md
Normal file
11
docs/ideas.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Ideas / backlog
|
||||||
|
|
||||||
|
## Analytics + server stats (analize.example.com)
|
||||||
|
|
||||||
|
- Public (or SSO-gated) web app that receives **web events** from my sites (page views, errors, custom events) and stores **server stats** from the homelab (per-service/module CPU, RAM, network, disk).
|
||||||
|
- Read side: dashboards — e.g. how much each service/module uses, event trends over time.
|
||||||
|
- Status: idea only. If built: one ingest API + a timeseries store (Postgres works fine at this scale), the same identity stack (Authelia SSO) in front, reverse-proxied by NPM. No code written yet.
|
||||||
|
|
||||||
|
## Autonomous AI agents (big idea)
|
||||||
|
|
||||||
|
- Ambitious project involving autonomous AI agents. Deferred — will revisit later.
|
||||||
|
|
@ -9,6 +9,7 @@ const servicesDir = join(repoRoot, "services");
|
||||||
const services: Catalog["services"] = [];
|
const services: Catalog["services"] = [];
|
||||||
|
|
||||||
for (const name of readdirSync(servicesDir).sort()) {
|
for (const name of readdirSync(servicesDir).sort()) {
|
||||||
|
if (!statSync(join(servicesDir, name), { throwIfNoEntry: false })?.isDirectory()) continue;
|
||||||
const metaPath = join(servicesDir, name, "metadata.json");
|
const metaPath = join(servicesDir, name, "metadata.json");
|
||||||
if (!statSync(metaPath, { throwIfNoEntry: false })?.isFile()) continue;
|
if (!statSync(metaPath, { throwIfNoEntry: false })?.isFile()) continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ function listLocal(dir: string): CatalogEntry[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const name of names.sort()) {
|
for (const name of names.sort()) {
|
||||||
|
if (!statSync(join(dir, name), { throwIfNoEntry: false })?.isDirectory()) continue;
|
||||||
const metaPath = join(dir, name, "metadata.json");
|
const metaPath = join(dir, name, "metadata.json");
|
||||||
if (!statSync(metaPath, { throwIfNoEntry: false })?.isFile()) continue;
|
if (!statSync(metaPath, { throwIfNoEntry: false })?.isFile()) continue;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
{
|
{
|
||||||
"generatedAt": "2026-09-02T16:59:46.903Z",
|
"generatedAt": "2026-09-10T21:29:23.464Z",
|
||||||
"services": [
|
"services": [
|
||||||
{
|
{
|
||||||
"id": "authelia",
|
"id": "authelia",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"path": "services/authelia/metadata.json"
|
"path": "services/authelia/metadata.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "forgejo",
|
||||||
|
"version": "11.0.0",
|
||||||
|
"path": "services/forgejo/metadata.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "lldap",
|
"id": "lldap",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
@ -25,6 +30,11 @@
|
||||||
"id": "portainer",
|
"id": "portainer",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"path": "services/portainer/metadata.json"
|
"path": "services/portainer/metadata.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "postgres",
|
||||||
|
"version": "17.0.0",
|
||||||
|
"path": "services/postgres/metadata.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
67
services/forgejo/metadata.json
Normal file
67
services/forgejo/metadata.json
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"id": "forgejo",
|
||||||
|
"name": "Forgejo",
|
||||||
|
"description": "Self-hosted Git service (web UI + git over SSH) backed by the homelab PostgreSQL.",
|
||||||
|
"version": "11.0.0",
|
||||||
|
"category": "development",
|
||||||
|
"tags": ["git", "forgejo", "vcs", "self-hosted", "codeberg"],
|
||||||
|
"author": "Forgejo contributors",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://forgejo.org/",
|
||||||
|
"documentation": "https://forgejo.org/docs/latest/",
|
||||||
|
"dependsOn": ["postgres"],
|
||||||
|
"compose": {
|
||||||
|
"image": "codeberg.org/forgejo/forgejo:11",
|
||||||
|
"container_name": "forgejo",
|
||||||
|
"restart": "unless-stopped",
|
||||||
|
"environment": [
|
||||||
|
"FORGEJO__database__TYPE=postgres",
|
||||||
|
"FORGEJO__database__HOST=homelab-postgres:5432",
|
||||||
|
"FORGEJO__database__NAME=${PG_DB}",
|
||||||
|
"FORGEJO__database__USER=${PG_USER}",
|
||||||
|
"FORGEJO__database__PASSWD=${PG_PASSWORD}",
|
||||||
|
"FORGEJO__server__ROOT_URL=${FORGEJO_ROOT_URL}",
|
||||||
|
"FORGEJO__server__SSH_DOMAIN=${FORGEJO_SSH_DOMAIN}",
|
||||||
|
"FORGEJO__server__SSH_PORT=2222",
|
||||||
|
"FORGEJO__service__DISABLE_REGISTRATION=true",
|
||||||
|
"TZ=${TZ}"
|
||||||
|
],
|
||||||
|
"ports": [
|
||||||
|
"10.0.0.5:3000:3000",
|
||||||
|
"10.0.0.5:2222:22"
|
||||||
|
],
|
||||||
|
"volumes": [
|
||||||
|
"forgejo_data:/data",
|
||||||
|
"/etc/timezone:/etc/timezone:ro",
|
||||||
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
|
],
|
||||||
|
"networks": ["homelab"]
|
||||||
|
},
|
||||||
|
"volumes": { "forgejo_data": {} },
|
||||||
|
"networks": { "homelab": { "external": true } },
|
||||||
|
"env": [
|
||||||
|
{ "name": "PG_USER", "label": "Postgres user", "default": "homelab" },
|
||||||
|
{ "name": "PG_DB", "label": "Postgres database", "default": "forgejo" },
|
||||||
|
{
|
||||||
|
"name": "PG_PASSWORD",
|
||||||
|
"label": "Postgres password",
|
||||||
|
"description": "Must match the postgres service. Pass --env PG_PASSWORD=<value from ~/.homelab/services/postgres/.env>",
|
||||||
|
"secret": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{ "name": "TZ", "label": "Timezone", "default": "UTC" },
|
||||||
|
{
|
||||||
|
"name": "FORGEJO_ROOT_URL",
|
||||||
|
"label": "Root URL",
|
||||||
|
"default": "http://10.0.0.5:3000/",
|
||||||
|
"description": "Switch to https://git.example.com/ once the reverse proxy is set up"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FORGEJO_SSH_DOMAIN",
|
||||||
|
"label": "SSH domain",
|
||||||
|
"default": "10.0.0.5",
|
||||||
|
"description": "Host used for git over SSH (port 2222)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"notes": "Web UI at http://10.0.0.5:3000 (LAN only) — create the first admin account there. Git over SSH: ssh://git@10.0.0.5:2222/<owner>/<repo>.git. Registration disabled (users via Authelia SSO later). Repos live in the forgejo_data volume; the database in pg_data (postgres service)."
|
||||||
|
}
|
||||||
44
services/postgres/metadata.json
Normal file
44
services/postgres/metadata.json
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"id": "postgres",
|
||||||
|
"name": "PostgreSQL",
|
||||||
|
"description": "Shared PostgreSQL database for homelab services (Forgejo today, future apps later).",
|
||||||
|
"version": "17.0.0",
|
||||||
|
"category": "database",
|
||||||
|
"tags": ["database", "sql", "postgres"],
|
||||||
|
"author": "PostgreSQL Global Development Group",
|
||||||
|
"license": "PostgreSQL",
|
||||||
|
"homepage": "https://www.postgresql.org/",
|
||||||
|
"documentation": "https://hub.docker.com/_/postgres",
|
||||||
|
"compose": {
|
||||||
|
"image": "postgres:17",
|
||||||
|
"container_name": "homelab-postgres",
|
||||||
|
"restart": "unless-stopped",
|
||||||
|
"environment": [
|
||||||
|
"POSTGRES_USER=${PG_USER}",
|
||||||
|
"POSTGRES_PASSWORD=${PG_PASSWORD}",
|
||||||
|
"POSTGRES_DB=${PG_DB}"
|
||||||
|
],
|
||||||
|
"volumes": ["pg_data:/var/lib/postgresql/data"],
|
||||||
|
"networks": ["homelab"],
|
||||||
|
"healthcheck": {
|
||||||
|
"test": ["CMD-SHELL", "pg_isready -U ${PG_USER} -d ${PG_DB}"],
|
||||||
|
"interval": "10s",
|
||||||
|
"timeout": "5s",
|
||||||
|
"retries": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"volumes": { "pg_data": {} },
|
||||||
|
"networks": { "homelab": { "external": true } },
|
||||||
|
"env": [
|
||||||
|
{ "name": "PG_USER", "label": "Postgres user", "default": "homelab" },
|
||||||
|
{
|
||||||
|
"name": "PG_PASSWORD",
|
||||||
|
"label": "Postgres password",
|
||||||
|
"description": "Auto-generated on first install and stored in ~/.homelab/services/postgres/.env",
|
||||||
|
"secret": true,
|
||||||
|
"generate": true
|
||||||
|
},
|
||||||
|
{ "name": "PG_DB", "label": "Database name", "default": "forgejo" }
|
||||||
|
],
|
||||||
|
"notes": "No host port published — reachable only inside the homelab docker network as `homelab-postgres`."
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue