[Feature Request] OIDC / Forward Auth #15

Closed
opened 2026-10-05 01:34:31 +02:00 by adam · 23 comments
Owner

Hi

It would be awesome to have OIDC or Forward auth, examples:

https://docs.goauthentik.io/docs/add-secure-apps/providers/proxy/header_authentication
https://docs.goauthentik.io/integrations/services/bookstack/

That would be awesome, because one could simply log into main auth provider and not have to log in again on each selfhosted app.
Therefore log in automatically into gitea-mirror.

I guess it's best to decide, if the app stays single-user then header auth may probably be the best, if multi-user OIDC/Oauth.

Hi It would be awesome to have OIDC or Forward auth, examples: https://docs.goauthentik.io/docs/add-secure-apps/providers/proxy/header_authentication https://docs.goauthentik.io/integrations/services/bookstack/ That would be awesome, because one could simply log into main auth provider and not have to log in again on each selfhosted app. Therefore log in automatically into gitea-mirror. I guess it's best to decide, if the app stays single-user then header auth may probably be the best, if multi-user OIDC/Oauth. <!-- github-sync-id:3168003753 -->
adam closed this issue 2026-10-05 01:34:31 +02:00
Author
Owner

I have been debating about single and multiple user casue I feel if people have multiple github accounts they could make seperate user accounts and have it work that way. but single account is just easier to manage. Will think more on it and see what I decide on

I have been debating about single and multiple user casue I feel if people have multiple github accounts they could make seperate user accounts and have it work that way. but single account is just easier to manage. Will think more on it and see what I decide on <!-- github-comment-id:2998814739 -->
Author
Owner

Yeah, I'd currently think single user is better for such a thing.
because with docker it's easy to run a second container.

Yeah, I'd currently think single user is better for such a thing. because with docker it's easy to run a second container. <!-- github-comment-id:2999338384 -->
Author
Owner

dude, you are insanely quick, awesome :)
will test out as soon as release is up.

dude, you are insanely quick, awesome :) will test out as soon as release is up. <!-- github-comment-id:3000120587 -->
Author
Owner
@CrazyWolf13 https://github.com/arunavo4/gitea-mirror/releases/tag/v2.19.0 <!-- github-comment-id:3000204544 -->
Author
Owner

Startup of the service seems to fail for me after update.

Jun 24 14:45:19 gitea-mirror bun[12782]: 🛑 Shutting down cleanup service...
Jun 24 14:45:19 gitea-mirror bun[12782]: 🛑 Stopping cleanup service...
Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Cleanup service stopped
Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Shutdown callback 1 completed
Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Completed all shutdown callbacks
Jun 24 14:45:19 gitea-mirror bun[12782]: 💾 Step 3: Closing database connections...
Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Graceful shutdown completed successfully
Jun 24 14:45:19 gitea-mirror systemd[1]: gitea-mirror.service: Deactivated successfully.
Jun 24 14:45:19 gitea-mirror systemd[1]: Stopped gitea-mirror.service - Gitea Mirror.
Jun 24 14:45:19 gitea-mirror systemd[1]: gitea-mirror.service: Consumed 1min 36.672s CPU time.
Jun 24 14:45:35 gitea-mirror systemd[1]: Started gitea-mirror.service - Gitea Mirror.
Jun 24 14:45:35 gitea-mirror bun[13390]: 14:45:35 [@astrojs/node] Server listening on
Jun 24 14:45:35 gitea-mirror bun[13390]:   local: https://localhost:4321
Jun 24 14:45:35 gitea-mirror bun[13390]:   network: https://10.10.20.47:4321
Jun 24 14:45:38 gitea-mirror bun[13390]: Successfully connected to SQLite database using Bun's native driver
Jun 24 14:45:38 gitea-mirror bun[13390]: ⚠️  Table 'auth_config' is missing. Creating it now...
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Table 'auth_config' created successfully
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Database migrations needed, running...
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Running database migrations...
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Migrating users table for authentication features...
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: display_name
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: auth_provider
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: external_id
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: external_username
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: is_active
Jun 24 14:45:38 gitea-mirror bun[13390]:   Adding column: last_login_at
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Applied 6 migrations to users table
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Creating auth_config table...
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ auth_config table already exists
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ All migrations completed successfully
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Database migrations completed successfully
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Initializing shutdown manager and signal handlers...
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Initializing shutdown manager...
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Shutdown manager initialized
Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Setting up signal handlers for graceful shutdown...
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Signal handlers registered successfully
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Shutdown manager and signal handlers initialized
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ No recovery needed (startup script likely handled it)
Jun 24 14:45:38 gitea-mirror bun[13390]: Starting automatic database cleanup service...
Jun 24 14:45:38 gitea-mirror bun[13390]: Starting background cleanup service...
Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Cleanup service started. Will run every 60 minutes.
Jun 24 14:45:50 gitea-mirror bun[13390]: 91 |       setLoading(false);
Jun 24 14:45:50 gitea-mirror bun[13390]: 92 |     }
Jun 24 14:45:50 gitea-mirror bun[13390]: 93 |   };
Jun 24 14:45:50 gitea-mirror bun[13390]: 94 |   return /* @__PURE__ */ jsxDEV("div", { className: "min-h-screen flex items-center justify-center p-4", children: /* @__PURE__ */ jsxDEV(Card, { className: "w-full max-w-2xl", children: [
Jun 24 14:45:50 gitea-mirror bun[13390]: 95 |     /* @__PURE__ */ jsxDEV(CardHeader, { children: [
Jun 24 14:45:50 gitea-mirror bun[13390]: 96 |       /* @__PURE__ */ jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, false, {
Jun 24 14:45:50 gitea-mirror bun[13390]:                            ^
Jun 24 14:45:50 gitea-mirror bun[13390]: TypeError: jsxDEV is not a function. (In 'jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, !1, {
Jun 24 14:45:50 gitea-mirror bun[13390]:         fileName: "/opt/gitea-mirror/src/components/auth/SetupWizard.tsx",
Jun 24 14:45:50 gitea-mirror bun[13390]:         lineNumber: 128,
Jun 24 14:45:50 gitea-mirror bun[13390]:         columnNumber: 11
Jun 24 14:45:50 gitea-mirror bun[13390]:       }, this)', 'jsxDEV' is undefined)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at SetupWizard (/opt/gitea-mirror/dist/server/pages/setup.astro.mjs:96:23)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at renderWithHooks (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3851:18)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at renderElement (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3989:14)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at retryNode (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:4591:16)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at performWork (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:5233:13)
Jun 24 14:45:50 gitea-mirror bun[13390]: There was an uncaught error in the middle of the stream while rendering /setup. 91 |       setLoading(false);
Jun 24 14:45:50 gitea-mirror bun[13390]: 92 |     }
Jun 24 14:45:50 gitea-mirror bun[13390]: 93 |   };
Jun 24 14:45:50 gitea-mirror bun[13390]: 94 |   return /* @__PURE__ */ jsxDEV("div", { className: "min-h-screen flex items-center justify-center p-4", children: /* @__PURE__ */ jsxDEV(Card, { className: "w-full max-w-2xl", children: [
Jun 24 14:45:50 gitea-mirror bun[13390]: 95 |     /* @__PURE__ */ jsxDEV(CardHeader, { children: [
Jun 24 14:45:50 gitea-mirror bun[13390]: 96 |       /* @__PURE__ */ jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, false, {
Jun 24 14:45:50 gitea-mirror bun[13390]:                            ^
Jun 24 14:45:50 gitea-mirror bun[13390]: TypeError: jsxDEV is not a function. (In 'jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, !1, {
Jun 24 14:45:50 gitea-mirror bun[13390]:         fileName: "/opt/gitea-mirror/src/components/auth/SetupWizard.tsx",
Jun 24 14:45:50 gitea-mirror bun[13390]:         lineNumber: 128,
Jun 24 14:45:50 gitea-mirror bun[13390]:         columnNumber: 11
Jun 24 14:45:50 gitea-mirror bun[13390]:       }, this)', 'jsxDEV' is undefined)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at SetupWizard (/opt/gitea-mirror/dist/server/pages/setup.astro.mjs:96:23)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at renderWithHooks (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3851:18)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at renderElement (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3989:14)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at retryNode (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:4591:16)
Jun 24 14:45:50 gitea-mirror bun[13390]:       at performWork (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:5233:13)
Startup of the service seems to fail for me after update. ```bash Jun 24 14:45:19 gitea-mirror bun[12782]: 🛑 Shutting down cleanup service... Jun 24 14:45:19 gitea-mirror bun[12782]: 🛑 Stopping cleanup service... Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Cleanup service stopped Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Shutdown callback 1 completed Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Completed all shutdown callbacks Jun 24 14:45:19 gitea-mirror bun[12782]: 💾 Step 3: Closing database connections... Jun 24 14:45:19 gitea-mirror bun[12782]: ✅ Graceful shutdown completed successfully Jun 24 14:45:19 gitea-mirror systemd[1]: gitea-mirror.service: Deactivated successfully. Jun 24 14:45:19 gitea-mirror systemd[1]: Stopped gitea-mirror.service - Gitea Mirror. Jun 24 14:45:19 gitea-mirror systemd[1]: gitea-mirror.service: Consumed 1min 36.672s CPU time. Jun 24 14:45:35 gitea-mirror systemd[1]: Started gitea-mirror.service - Gitea Mirror. Jun 24 14:45:35 gitea-mirror bun[13390]: 14:45:35 [@astrojs/node] Server listening on Jun 24 14:45:35 gitea-mirror bun[13390]: local: https://localhost:4321 Jun 24 14:45:35 gitea-mirror bun[13390]: network: https://10.10.20.47:4321 Jun 24 14:45:38 gitea-mirror bun[13390]: Successfully connected to SQLite database using Bun's native driver Jun 24 14:45:38 gitea-mirror bun[13390]: ⚠️ Table 'auth_config' is missing. Creating it now... Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Table 'auth_config' created successfully Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Database migrations needed, running... Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Running database migrations... Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Migrating users table for authentication features... Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: display_name Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: auth_provider Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: external_id Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: external_username Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: is_active Jun 24 14:45:38 gitea-mirror bun[13390]: Adding column: last_login_at Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Applied 6 migrations to users table Jun 24 14:45:38 gitea-mirror bun[13390]: 🔄 Creating auth_config table... Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ auth_config table already exists Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ All migrations completed successfully Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Database migrations completed successfully Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Initializing shutdown manager and signal handlers... Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Initializing shutdown manager... Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Shutdown manager initialized Jun 24 14:45:38 gitea-mirror bun[13390]: 🔧 Setting up signal handlers for graceful shutdown... Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Signal handlers registered successfully Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Shutdown manager and signal handlers initialized Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ No recovery needed (startup script likely handled it) Jun 24 14:45:38 gitea-mirror bun[13390]: Starting automatic database cleanup service... Jun 24 14:45:38 gitea-mirror bun[13390]: Starting background cleanup service... Jun 24 14:45:38 gitea-mirror bun[13390]: ✅ Cleanup service started. Will run every 60 minutes. Jun 24 14:45:50 gitea-mirror bun[13390]: 91 | setLoading(false); Jun 24 14:45:50 gitea-mirror bun[13390]: 92 | } Jun 24 14:45:50 gitea-mirror bun[13390]: 93 | }; Jun 24 14:45:50 gitea-mirror bun[13390]: 94 | return /* @__PURE__ */ jsxDEV("div", { className: "min-h-screen flex items-center justify-center p-4", children: /* @__PURE__ */ jsxDEV(Card, { className: "w-full max-w-2xl", children: [ Jun 24 14:45:50 gitea-mirror bun[13390]: 95 | /* @__PURE__ */ jsxDEV(CardHeader, { children: [ Jun 24 14:45:50 gitea-mirror bun[13390]: 96 | /* @__PURE__ */ jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, false, { Jun 24 14:45:50 gitea-mirror bun[13390]: ^ Jun 24 14:45:50 gitea-mirror bun[13390]: TypeError: jsxDEV is not a function. (In 'jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, !1, { Jun 24 14:45:50 gitea-mirror bun[13390]: fileName: "/opt/gitea-mirror/src/components/auth/SetupWizard.tsx", Jun 24 14:45:50 gitea-mirror bun[13390]: lineNumber: 128, Jun 24 14:45:50 gitea-mirror bun[13390]: columnNumber: 11 Jun 24 14:45:50 gitea-mirror bun[13390]: }, this)', 'jsxDEV' is undefined) Jun 24 14:45:50 gitea-mirror bun[13390]: at SetupWizard (/opt/gitea-mirror/dist/server/pages/setup.astro.mjs:96:23) Jun 24 14:45:50 gitea-mirror bun[13390]: at renderWithHooks (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3851:18) Jun 24 14:45:50 gitea-mirror bun[13390]: at renderElement (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3989:14) Jun 24 14:45:50 gitea-mirror bun[13390]: at retryNode (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:4591:16) Jun 24 14:45:50 gitea-mirror bun[13390]: at performWork (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:5233:13) Jun 24 14:45:50 gitea-mirror bun[13390]: There was an uncaught error in the middle of the stream while rendering /setup. 91 | setLoading(false); Jun 24 14:45:50 gitea-mirror bun[13390]: 92 | } Jun 24 14:45:50 gitea-mirror bun[13390]: 93 | }; Jun 24 14:45:50 gitea-mirror bun[13390]: 94 | return /* @__PURE__ */ jsxDEV("div", { className: "min-h-screen flex items-center justify-center p-4", children: /* @__PURE__ */ jsxDEV(Card, { className: "w-full max-w-2xl", children: [ Jun 24 14:45:50 gitea-mirror bun[13390]: 95 | /* @__PURE__ */ jsxDEV(CardHeader, { children: [ Jun 24 14:45:50 gitea-mirror bun[13390]: 96 | /* @__PURE__ */ jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, false, { Jun 24 14:45:50 gitea-mirror bun[13390]: ^ Jun 24 14:45:50 gitea-mirror bun[13390]: TypeError: jsxDEV is not a function. (In 'jsxDEV(CardTitle, { className: "text-2xl", children: "Welcome to Gitea Mirror" }, void 0, !1, { Jun 24 14:45:50 gitea-mirror bun[13390]: fileName: "/opt/gitea-mirror/src/components/auth/SetupWizard.tsx", Jun 24 14:45:50 gitea-mirror bun[13390]: lineNumber: 128, Jun 24 14:45:50 gitea-mirror bun[13390]: columnNumber: 11 Jun 24 14:45:50 gitea-mirror bun[13390]: }, this)', 'jsxDEV' is undefined) Jun 24 14:45:50 gitea-mirror bun[13390]: at SetupWizard (/opt/gitea-mirror/dist/server/pages/setup.astro.mjs:96:23) Jun 24 14:45:50 gitea-mirror bun[13390]: at renderWithHooks (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3851:18) Jun 24 14:45:50 gitea-mirror bun[13390]: at renderElement (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:3989:14) Jun 24 14:45:50 gitea-mirror bun[13390]: at retryNode (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:4591:16) Jun 24 14:45:50 gitea-mirror bun[13390]: at performWork (/opt/gitea-mirror/node_modules/react-dom/cjs/react-dom-server.bun.production.js:5233:13) ``` <!-- github-comment-id:3000324836 -->
Author
Owner

@CrazyWolf13 are you using docker or Proxmox?

@CrazyWolf13 are you using docker or Proxmox? <!-- github-comment-id:3000419635 -->
Author
Owner

Proxmox :)

Proxmox :) <!-- github-comment-id:3000463398 -->
Author
Owner

@CrazyWolf13 I have made a patch update with some manual migrations. But will be releasing a breaking change major verison update with drizzle migrations for future proofing this.

Production build error fix:

cd /opt/gitea-mirror
NODE_ENV=production bun run build
sudo systemctl restart gitea-mirror

Setup wizard on existing installation fix:

cd /opt/gitea-mirror
./fix-v2.19-upgrade.sh
@CrazyWolf13 I have made a patch update with some manual migrations. But will be releasing a breaking change major verison update with drizzle migrations for future proofing this. Production build error fix: ``` cd /opt/gitea-mirror NODE_ENV=production bun run build sudo systemctl restart gitea-mirror ``` Setup wizard on existing installation fix: ``` cd /opt/gitea-mirror ./fix-v2.19-upgrade.sh ``` <!-- github-comment-id:3000607738 -->
Author
Owner

Hi @arunavo4
Thanks for the quick fix, though that does not seem to resolve the issue, I still see the error:

Neither the update, nor the both snippets above seem to fix it :/

Image

The first command did just a build no special output, but the service still showed the above error.

The second command looks promising, but seems to fail.

Hi @arunavo4 Thanks for the quick fix, though that does not seem to resolve the issue, I still see the error: Neither the update, nor the both snippets above seem to fix it :/ ![Image](https://github.com/user-attachments/assets/4ffcf01e-adef-4d1d-acdd-ed69a9614a62) The first command did just a build no special output, but the service still showed the above error. The second command looks promising, but seems to fail. <!-- github-comment-id:3000805990 -->
Author
Owner

@CrazyWolf13 Hey I dont want to spend time writing migrations so I have moved the application to use drizzle migrations for easy migrations in the future but it does come with a major breaking change so just do a fresh start from scratch.

future migrations should be seemless. v3.0.0 I am currently testing this

@CrazyWolf13 Hey I dont want to spend time writing migrations so I have moved the application to use drizzle migrations for easy migrations in the future but it does come with a major breaking change so just do a fresh start from scratch. future migrations should be seemless. `v3.0.0` I am currently testing this <!-- github-comment-id:3000842136 -->
Author
Owner

alright.

Please let me know the most semless way to migrate the whole community-script userbase (Roughly 100 Installs)
Plus if we need to do any special changes to our deployment.

alright. Please let me know the most semless way to migrate the whole community-script userbase (Roughly 100 Installs) Plus if we need to do any special changes to our deployment. <!-- github-comment-id:3000919565 -->
Author
Owner

@arunavo4 could you release v3 as an actual github release an tag it?
Seems like it's ony tagged on ghcr.

EDIT: seems like it's only prerelease.

@arunavo4 could you release v3 as an actual github release an tag it? Seems like it's ony tagged on ghcr. EDIT: seems like it's only prerelease. <!-- github-comment-id:3011689647 -->
Author
Owner

It has issues so I have made pre release I need to fix the issues but I don't have time this week wait for next week I will try to find some time

It has issues so I have made pre release I need to fix the issues but I don't have time this week wait for next week I will try to find some time <!-- github-comment-id:3012546213 -->
Author
Owner

Due to major issues I have removed the v3 branch and will update it once I have fully tested and fixed all the issues.

Due to major issues I have removed the v3 branch and will update it once I have fully tested and fixed all the issues. <!-- github-comment-id:3043468208 -->
Author
Owner

@CrazyWolf13 consider testing the latest v3 version

https://github.com/RayLabsHQ/gitea-mirror/releases/tag/v3.0.0

@CrazyWolf13 consider testing the latest v3 version https://github.com/RayLabsHQ/gitea-mirror/releases/tag/v3.0.0 <!-- github-comment-id:3083711481 -->
Author
Owner

@arunavo4 apologies for the delay, I was finally able to upgrade our script and also my personal instance. I fully reconfigured it too.

When clicking on the Authentification Part of that round bar, I end up with a black screen, I can't see anything in the log.

https://github.com/user-attachments/assets/9824c1bf-560d-4157-9b76-6ab0420cb4a5

@arunavo4 apologies for the delay, I was finally able to upgrade our script and also my personal instance. I fully reconfigured it too. When clicking on the Authentification Part of that round bar, I end up with a black screen, I can't see anything in the log. https://github.com/user-attachments/assets/9824c1bf-560d-4157-9b76-6ab0420cb4a5 <!-- github-comment-id:3103995914 -->
Author
Owner

Error from dev-tools:

Uncaught TypeError: t.map is not a function
    Z0 http://10.10.20.45:4321/_astro/MainLayout.aKav2rrH.js:273
    Rf http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    $f http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    A1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    w1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    Hh http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    zc http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    C1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    fv http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24
    Ea http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9
    Td http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9
    Td http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9
    Ed http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9
    Md http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:17
    Dd http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:25
    <anonymous> http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:25
MainLayout.aKav2rrH.js:273:134771
Error from dev-tools: ```bash Uncaught TypeError: t.map is not a function Z0 http://10.10.20.45:4321/_astro/MainLayout.aKav2rrH.js:273 Rf http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 $f http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 A1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 w1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 Hh http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 zc http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 C1 http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 fv http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:24 Ea http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9 Td http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9 Td http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9 Ed http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:9 Md http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:17 Dd http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:25 <anonymous> http://10.10.20.45:4321/_astro/client.DxZNQU9M.js:25 MainLayout.aKav2rrH.js:273:134771 ``` <!-- github-comment-id:3104001447 -->
Author
Owner

I'm gonna close this as OIDC is implemented.

I'm gonna close this as OIDC is implemented. <!-- github-comment-id:3430649558 -->
Author
Owner

Checking in on this — as of v3.9.2, HTTP header / forward auth doesn't appear to be available in the UI anymore. The only options under "Add SSO Provider" are OIDC/OAuth2 and SAML 2.0. Was this dropped in the v3 rewrite, or is it still planned?

Checking in on this — as of v3.9.2, HTTP header / forward auth doesn't appear to be available in the UI anymore. The only options under "Add SSO Provider" are OIDC/OAuth2 and SAML 2.0. Was this dropped in the v3 rewrite, or is it still planned? <!-- github-comment-id:4529363082 -->
Author
Owner

Hey @lanrat — header / forward auth is still supported in v3, it just isn't exposed in the "Add SSO Provider" dialog. That dialog is for OIDC/OAuth/SAML providers, which we store in the DB so per-user provisioning can be managed from the UI.

Header auth is intentionally environment-variable only, because trusting a header means trusting whatever upstream sets it — that's an operator-level decision (who controls the reverse proxy), not something a logged-in user inside the app should be able to flip on. So it lives outside the UI provider list.

Minimum config to turn it on:

environment:
  HEADER_AUTH_ENABLED: "true"
  HEADER_AUTH_AUTO_PROVISION: "true"   # optional, lets first login create the user

The defaults are Authentik-shaped (X-Authentik-Username / -Email / -Name); for Authelia or oauth2-proxy override HEADER_AUTH_USER_HEADER / _EMAIL_HEADER / _NAME_HEADER. Full variable list is in docs/ENVIRONMENT_VARIABLES.md.

Once it's active you'll see a green "Header Authentication / Via reverse proxy" badge on the Authentication settings page, and /api/auth/header-status returns {"enabled": true, ...}.

Acknowledged that this wasn't discoverable — just landed a section in docs/SSO-OIDC-SETUP.md covering setup, Authentik + Authelia examples, lookup order, and the must-strip-inbound-headers security note.

Hey @lanrat — header / forward auth is still supported in v3, it just isn't exposed in the "Add SSO Provider" dialog. That dialog is for OIDC/OAuth/SAML providers, which we store in the DB so per-user provisioning can be managed from the UI. Header auth is intentionally **environment-variable only**, because trusting a header means trusting whatever upstream sets it — that's an operator-level decision (who controls the reverse proxy), not something a logged-in user inside the app should be able to flip on. So it lives outside the UI provider list. Minimum config to turn it on: ```yaml environment: HEADER_AUTH_ENABLED: "true" HEADER_AUTH_AUTO_PROVISION: "true" # optional, lets first login create the user ``` The defaults are Authentik-shaped (`X-Authentik-Username` / `-Email` / `-Name`); for Authelia or oauth2-proxy override `HEADER_AUTH_USER_HEADER` / `_EMAIL_HEADER` / `_NAME_HEADER`. Full variable list is in [`docs/ENVIRONMENT_VARIABLES.md`](https://github.com/RayLabsHQ/gitea-mirror/blob/main/docs/ENVIRONMENT_VARIABLES.md#header-authentication-reverse-proxy-sso). Once it's active you'll see a green "Header Authentication / Via reverse proxy" badge on the Authentication settings page, and `/api/auth/header-status` returns `{"enabled": true, ...}`. Acknowledged that this wasn't discoverable — just landed a section in [`docs/SSO-OIDC-SETUP.md`](https://github.com/RayLabsHQ/gitea-mirror/blob/main/docs/SSO-OIDC-SETUP.md#setting-up-header--forward-authentication) covering setup, Authentik + Authelia examples, lookup order, and the must-strip-inbound-headers security note. <!-- github-comment-id:4531678219 -->
Author
Owner

Thanks for the reply — I gave it another shot on v3.16.1 with header overrides matching what Caddy / caddy-security sends, and it still doesn't work end to end. Server side picks up the headers fine, but the browser ends up back at /login.

Config:

HEADER_AUTH_ENABLED: "true"
HEADER_AUTH_AUTO_PROVISION: "true"
HEADER_AUTH_USER_HEADER: "X-Token-User-Email"
HEADER_AUTH_EMAIL_HEADER: "X-Token-User-Email"
HEADER_AUTH_NAME_HEADER: "X-Token-User-Name"

Config is being loaded — /api/auth/header-status reports it:

$ docker exec git-mirror sh -c 'wget -qO- http://localhost:4321/api/auth/header-status'
{"enabled":true,"userHeader":"X-Token-User-Email","autoProvision":true,"hasAllowedDomains":true}

Cleanest repro, no proxy involved — running inside the container:

$ docker exec git-mirror sh -c 'wget -qO- \
    --header="X-Token-User-Email: user@example.com" \
    --header="X-Token-User-Name: User" \
    http://localhost:4321/api/auth/get-session'
null

That's a 200 with body null even with the headers right there on the request. The React app calls this on mount, sees null, and the auth guard punts to /login.

Looking at the source, I think this is what's going on:

  • src/middleware.ts L43–71 populates context.locals.user/session on header-auth success, but never sets a cookie, so nothing about the auth state survives the response.
  • src/pages/api/auth/[...all].ts hands the whole /api/auth/* surface off to auth.handler (Better Auth), which only knows about cookies — so get-session can't see the header-authenticated user.

Two ways out I can see: either the middleware mints a real Better Auth session/cookie when header auth succeeds, or get-session falls through to the header check when there's no cookie. Either one would unstick the SPA.

If you push a fix I'm happy to test. It feels like header auth is one cookie away from working.

Thanks for the reply — I gave it another shot on v3.16.1 with header overrides matching what Caddy / caddy-security sends, and it still doesn't work end to end. Server side picks up the headers fine, but the browser ends up back at `/login`. Config: ```yaml HEADER_AUTH_ENABLED: "true" HEADER_AUTH_AUTO_PROVISION: "true" HEADER_AUTH_USER_HEADER: "X-Token-User-Email" HEADER_AUTH_EMAIL_HEADER: "X-Token-User-Email" HEADER_AUTH_NAME_HEADER: "X-Token-User-Name" ``` Config is being loaded — `/api/auth/header-status` reports it: ``` $ docker exec git-mirror sh -c 'wget -qO- http://localhost:4321/api/auth/header-status' {"enabled":true,"userHeader":"X-Token-User-Email","autoProvision":true,"hasAllowedDomains":true} ``` Cleanest repro, no proxy involved — running inside the container: ``` $ docker exec git-mirror sh -c 'wget -qO- \ --header="X-Token-User-Email: user@example.com" \ --header="X-Token-User-Name: User" \ http://localhost:4321/api/auth/get-session' null ``` That's a 200 with body `null` even with the headers right there on the request. The React app calls this on mount, sees `null`, and the auth guard punts to `/login`. Looking at the source, I think this is what's going on: - [`src/middleware.ts` L43–71](https://github.com/RayLabsHQ/gitea-mirror/blob/main/src/middleware.ts#L43-L71) populates `context.locals.user`/`session` on header-auth success, but never sets a cookie, so nothing about the auth state survives the response. - [`src/pages/api/auth/[...all].ts`](https://github.com/RayLabsHQ/gitea-mirror/blob/main/src/pages/api/auth/%5B...all%5D.ts) hands the whole `/api/auth/*` surface off to `auth.handler` (Better Auth), which only knows about cookies — so `get-session` can't see the header-authenticated user. Two ways out I can see: either the middleware mints a real Better Auth session/cookie when header auth succeeds, or `get-session` falls through to the header check when there's no cookie. Either one would unstick the SPA. If you push a fix I'm happy to test. It feels like header auth is one cookie away from working. <!-- github-comment-id:4535915584 -->
Author
Owner

@lanrat thanks for testing it out. please give the latest version a try

@lanrat thanks for testing it out. please give the latest version a try <!-- github-comment-id:4554817202 -->
Author
Owner

Header auth works now. Thanks!

Header auth works now. Thanks! <!-- github-comment-id:4556040057 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/gitea-mirror#15