diff --git a/.dockerignore b/.dockerignore index 4ec17391..94cf9d0a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,3 +3,6 @@ static htmlcov *.env.yml **/node_modules +dist/** +build/** +build_docs/** diff --git a/Dockerfile b/Dockerfile index b07ffc8a..760de54f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,15 @@ RUN pip install pipenv && \ pipenv lock -r > requirements.txt && \ pipenv lock -r --dev-only > requirements-dev.txt -# Stage 2: Build web API +# Stage 2: Build website +FROM node as website-builder + +COPY ./website /static/ + +ENV NODE_ENV=production +RUN cd /static && npm i && npm run build-docs-only + +# Stage 3: Build web API FROM openapitools/openapi-generator-cli as api-builder COPY ./schema.yml /local/schema.yml @@ -21,8 +29,8 @@ RUN docker-entrypoint.sh generate \ -o /local/web/api \ --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0 -# Stage 3: Build webui -FROM node as npm-builder +# Stage 4: Build webui +FROM node as web-builder COPY ./web /static/ COPY --from=api-builder /local/web/api /static/api @@ -30,15 +38,16 @@ COPY --from=api-builder /local/web/api /static/api ENV NODE_ENV=production RUN cd /static && npm i && npm run build -# Stage 4: Build go proxy +# Stage 5: Build go proxy FROM golang:1.16.5 AS builder WORKDIR /work -COPY --from=npm-builder /static/robots.txt /work/web/robots.txt -COPY --from=npm-builder /static/security.txt /work/web/security.txt -COPY --from=npm-builder /static/dist/ /work/web/dist/ -COPY --from=npm-builder /static/authentik/ /work/web/authentik/ +COPY --from=web-builder /static/robots.txt /work/web/robots.txt +COPY --from=web-builder /static/security.txt /work/web/security.txt +COPY --from=web-builder /static/dist/ /work/web/dist/ +COPY --from=web-builder /static/authentik/ /work/web/authentik/ +COPY --from=website-builder /static/build_docs/ /work/website/build_docs/ COPY ./cmd /work/cmd COPY ./web/static.go /work/web/static.go @@ -48,7 +57,7 @@ COPY ./go.sum /work/go.sum RUN go build -o /work/authentik ./cmd/server/main.go -# Stage 5: Run +# Stage 6: Run FROM python:3.9-slim-buster WORKDIR / diff --git a/internal/web/web_static.go b/internal/web/web_static.go index ccee1c98..11c0d0e9 100644 --- a/internal/web/web_static.go +++ b/internal/web/web_static.go @@ -6,6 +6,7 @@ import ( "goauthentik.io/internal/config" "goauthentik.io/internal/constants" staticWeb "goauthentik.io/web" + staticDocs "goauthentik.io/website" ) func (ws *WebServer) configureStatic() { @@ -17,12 +18,14 @@ func (ws *WebServer) configureStatic() { statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static/dist", http.FileServer(http.Dir("./web/dist")))) statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static/authentik", http.FileServer(http.Dir("./web/authentik")))) statRouter.PathPrefix("/media").Handler(http.StripPrefix("/media", fs)) + statRouter.PathPrefix("/help").Handler(http.StripPrefix("/help", http.FileServer(http.Dir("./website/build_docs")))) } else { statRouter.Use(ws.staticHeaderMiddleware) ws.log.Debug("Using packaged static files with aggressive caching") statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticDist)))) statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticAuthentik)))) statRouter.PathPrefix("/media").Handler(http.StripPrefix("/media", fs)) + statRouter.PathPrefix("/help").Handler(http.StripPrefix("/help", http.FileServer(http.FS(staticDocs.DocsDist)))) } ws.lh.Path("/robots.txt").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Header()["Content-Type"] = []string{"text/plain"} diff --git a/website/.gitignore b/website/.gitignore index b2d6de30..67a2e806 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -3,6 +3,7 @@ # Production /build +/build_docs # Generated files .docusaurus diff --git a/website/docusaurus.docs-only.js b/website/docusaurus.docs-only.js new file mode 100644 index 00000000..eabd0840 --- /dev/null +++ b/website/docusaurus.docs-only.js @@ -0,0 +1,86 @@ +const mainConfig = require("./docusaurus.config"); + +module.exports = { + title: "authentik", + tagline: "Making authentication simple.", + url: "https://goauthentik.io", + baseUrl: "/help/", + onBrokenLinks: "throw", + favicon: "img/icon.png", + organizationName: "BeryJu", + projectName: "authentik", + themeConfig: { + navbar: { + title: "authentik", + logo: { + alt: "authentik logo", + src: "img/icon_left_brand.svg", + }, + items: [ + { + to: "docs/", + activeBasePath: "docs", + label: "Docs", + position: "left", + }, + { + to: "developer-docs/", + activeBasePath: "developer-docs", + label: "Developer Docs", + position: "left", + }, + { + href: "https://github.com/goauthentik/authentik", + label: "GitHub", + position: "right", + }, + { + href: "https://discord.gg/jg33eMhnj6", + label: "Discord", + position: "right", + }, + ], + }, + footer: mainConfig.themeConfig.footer, + colorMode: mainConfig.themeConfig.colorMode, + }, + presets: [ + [ + "@docusaurus/preset-classic", + { + docs: { + id: "docs", + sidebarPath: require.resolve("./sidebars.js"), + editUrl: "https://github.com/goauthentik/authentik/edit/master/website/", + }, + pages: false, + theme: { + customCss: require.resolve("./src/css/custom.css"), + }, + }, + ], + ], + plugins: [ + [ + '@docusaurus/plugin-content-docs', + { + id: 'docsDevelopers', + path: 'developer-docs', + routeBasePath: 'developer-docs', + sidebarPath: require.resolve('./sidebarsDev.js'), + editUrl: "https://github.com/goauthentik/authentik/edit/master/website/", + }, + ], + [ + '@docusaurus/plugin-client-redirects', + { + redirects: [ + { + to: '/docs/', + from: ['/'], + }, + ], + }, + ], + ], +}; diff --git a/website/package-lock.json b/website/package-lock.json index 2fb988e1..7eb98b81 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -8,6 +8,7 @@ "name": "authentik-docs", "version": "0.0.0", "dependencies": { + "@docusaurus/plugin-client-redirects": "*", "@docusaurus/preset-classic": "2.0.0-beta.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", @@ -1781,6 +1782,42 @@ "react-dom": "^16.8.4 || ^17.0.0" } }, + "node_modules/@docusaurus/plugin-client-redirects": { + "version": "2.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-2.0.0-beta.0.tgz", + "integrity": "sha512-8USMnBo9YkcA/MFUBtTv2U+Me5uQih7cpAkgOhLkn9DwdgMoKNmcA+RGVLyKvczimYW4LpAZi+NoNqrJ7FkAkw==", + "dependencies": { + "@docusaurus/core": "2.0.0-beta.0", + "@docusaurus/types": "2.0.0-beta.0", + "@docusaurus/utils": "2.0.0-beta.0", + "@docusaurus/utils-validation": "2.0.0-beta.0", + "chalk": "^3.0.0", + "eta": "^1.11.0", + "fs-extra": "^9.1.0", + "globby": "^11.0.2", + "lodash": "^4.17.20", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10.9.0" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0", + "react-dom": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/@docusaurus/plugin-client-redirects/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@docusaurus/plugin-content-blog": { "version": "2.0.0-beta.0", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.0.tgz", @@ -16461,6 +16498,34 @@ "webpack": "^5.28.0" } }, + "@docusaurus/plugin-client-redirects": { + "version": "2.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-2.0.0-beta.0.tgz", + "integrity": "sha512-8USMnBo9YkcA/MFUBtTv2U+Me5uQih7cpAkgOhLkn9DwdgMoKNmcA+RGVLyKvczimYW4LpAZi+NoNqrJ7FkAkw==", + "requires": { + "@docusaurus/core": "2.0.0-beta.0", + "@docusaurus/types": "2.0.0-beta.0", + "@docusaurus/utils": "2.0.0-beta.0", + "@docusaurus/utils-validation": "2.0.0-beta.0", + "chalk": "^3.0.0", + "eta": "^1.11.0", + "fs-extra": "^9.1.0", + "globby": "^11.0.2", + "lodash": "^4.17.20", + "tslib": "^2.1.0" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, "@docusaurus/plugin-content-blog": { "version": "2.0.0-beta.0", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.0.tgz", diff --git a/website/package.json b/website/package.json index 9f590600..f65f880a 100644 --- a/website/package.json +++ b/website/package.json @@ -6,11 +6,13 @@ "docusaurus": "docusaurus", "watch": "docusaurus start", "build": "docusaurus build", + "build-docs-only": "docusaurus build --config docusaurus.docs-only.js --out-dir build_docs", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "serve": "docusaurus serve" }, "dependencies": { + "@docusaurus/plugin-client-redirects": "*", "@docusaurus/preset-classic": "2.0.0-beta.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", diff --git a/website/static.go b/website/static.go new file mode 100644 index 00000000..2634b0f5 --- /dev/null +++ b/website/static.go @@ -0,0 +1,6 @@ +package web + +import "embed" + +//go:embed build_docs/* +var DocsDist embed.FS