diff --git a/hosts/koi/configuration.nix b/hosts/koi/configuration.nix index 9475ee6..951adc4 100755 --- a/hosts/koi/configuration.nix +++ b/hosts/koi/configuration.nix @@ -32,6 +32,7 @@ ./containers/zond ./containers/authentik ./containers/outline-wiki + ./containers/siyuan ./containers/teisu.nix ./containers/bots/pcre-sub-bot.nix ./containers/bots/channel-logger-bot.nix diff --git a/hosts/koi/containers/siyuan/default.nix b/hosts/koi/containers/siyuan/default.nix new file mode 100644 index 0000000..d3d3b92 --- /dev/null +++ b/hosts/koi/containers/siyuan/default.nix @@ -0,0 +1,63 @@ +{ abs, pkgs, config, ... }@inputs: + +let + secrets = import (abs "lib/secrets.nix"); + trivial = import (abs "lib/trivial.nix") inputs; + + UID = 1113; + context = trivial.storeDirectory ./image; +in { + imports = [ + (secrets.declare [{ + name = "siyuan-teidesu-authentik-env"; + owner = "siyuan-teidesu"; + }]) + ]; + users.users.siyuan-teidesu = { + isNormalUser = true; + uid = UID; + }; + + systemd.services.docker-siyuan-teidesu.serviceConfig.ExecStartPre = [ + (pkgs.writeShellScript "build-siyuan" '' + docker build -t local/siyuan ${context} + '') + ]; + virtualisation.oci-containers.containers.siyuan-teidesu = { + image = "local/siyuan"; + volumes = [ + "/srv/siyuan-teidesu:/data" + ]; + cmd = [ "--workspace=/data" ]; + environment = { + # we manage auth via authentik + SIYUAN_ACCESS_AUTH_CODE_BYPASS = "true"; + }; + user = builtins.toString UID; + }; + + virtualisation.oci-containers.containers.siyuan-teidesu-authentik = { + image = "ghcr.io/goauthentik/proxy"; + environment = { + AUTHENTIK_HOST = "https://id.stupid.fish"; + }; + user = builtins.toString UID; + environmentFiles = [ + (secrets.file config "siyuan-teidesu-authentik-env") + ]; + }; + + systemd.tmpfiles.rules = [ + "d /srv/siyuan-teidesu 0700 ${builtins.toString UID} ${builtins.toString UID} -" + ]; + + services.nginx.virtualHosts."siyuan.tei.su" = { + forceSSL = true; + useACMEHost = "tei.su"; + + locations."/" = { + proxyPass = "http://siyuan-teidesu-authentik.docker:9000$request_uri"; + proxyWebsockets = true; + }; + }; +} \ No newline at end of file diff --git a/hosts/koi/containers/siyuan/image/Dockerfile b/hosts/koi/containers/siyuan/image/Dockerfile new file mode 100644 index 0000000..d480ff5 --- /dev/null +++ b/hosts/koi/containers/siyuan/image/Dockerfile @@ -0,0 +1,60 @@ +# based on https://github.com/siyuan-note/siyuan/blob/master/Dockerfile +FROM node:21 as NODE_BUILD +ARG COMMIT=3eec016723f52f3a679fb99854ae33e8fe20e42a + +# fetch and patch +ADD *.patch /patches/ +RUN apt-get update && \ + apt-get install -y git jq && \ + git clone https://github.com/siyuan-note/siyuan.git /go/src/github.com/siyuan-note/siyuan/ --depth=1 && \ + cd /go/src/github.com/siyuan-note/siyuan/ && \ + git fetch --depth=1 origin ${COMMIT} && \ + git checkout ${COMMIT} && \ + git submodule update --init --recursive && \ + git apply /patches/license.patch + +WORKDIR /go/src/github.com/siyuan-note/siyuan/ +# the rest is pretty much the same as the official Dockerfile + +RUN cd app && \ +packageManager=$(jq -r '.packageManager' package.json) && \ +if [ -n "$packageManager" ]; then \ + npm install -g $packageManager; \ +else \ + echo "No packageManager field found in package.json"; \ + npm install -g pnpm; \ +fi && \ +pnpm install --registry=http://registry.npmjs.org/ --silent && \ +pnpm run build +RUN apt-get purge -y jq +RUN apt-get autoremove -y +RUN rm -rf /var/lib/apt/lists/* + +FROM golang:alpine as GO_BUILD +WORKDIR /go/src/github.com/siyuan-note/siyuan/ +COPY --from=NODE_BUILD /go/src/github.com/siyuan-note/siyuan/ /go/src/github.com/siyuan-note/siyuan/ +ENV GO111MODULE=on +ENV CGO_ENABLED=1 +RUN apk add --no-cache gcc musl-dev && \ + cd kernel && go build --tags fts5 -v -ldflags "-s -w" && \ + mkdir /opt/siyuan/ && \ + mv /go/src/github.com/siyuan-note/siyuan/app/appearance/ /opt/siyuan/ && \ + mv /go/src/github.com/siyuan-note/siyuan/app/stage/ /opt/siyuan/ && \ + mv /go/src/github.com/siyuan-note/siyuan/app/guide/ /opt/siyuan/ && \ + mv /go/src/github.com/siyuan-note/siyuan/app/changelogs/ /opt/siyuan/ && \ + mv /go/src/github.com/siyuan-note/siyuan/kernel/kernel /opt/siyuan/ && \ + find /opt/siyuan/ -name .git | xargs rm -rf + +FROM alpine:latest +LABEL maintainer="Liang Ding<845765@qq.com>" + +WORKDIR /opt/siyuan/ +COPY --from=GO_BUILD /opt/siyuan/ /opt/siyuan/ +RUN addgroup --gid 1113 siyuan && adduser --uid 1113 --ingroup siyuan --disabled-password siyuan && apk add --no-cache ca-certificates tzdata && chown -R siyuan:siyuan /opt/siyuan/ + +ENV TZ=Asia/Shanghai +ENV RUN_IN_CONTAINER=true +EXPOSE 6806 + +USER siyuan +ENTRYPOINT ["/opt/siyuan/kernel"] \ No newline at end of file diff --git a/hosts/koi/containers/siyuan/image/license.patch b/hosts/koi/containers/siyuan/image/license.patch new file mode 100644 index 0000000..5f49743 --- /dev/null +++ b/hosts/koi/containers/siyuan/image/license.patch @@ -0,0 +1,121 @@ +diff --git a/app/src/util/needSubscribe.ts b/app/src/util/needSubscribe.ts +index 6ba7848..329ef97 100644 +--- a/app/src/util/needSubscribe.ts ++++ b/app/src/util/needSubscribe.ts +@@ -2,22 +2,9 @@ import {showMessage} from "../dialog/message"; + import {getCloudURL} from "../config/util/about"; + + export const needSubscribe = (tip = window.siyuan.languages._kernel[29]) => { +- if (window.siyuan.user && (window.siyuan.user.userSiYuanProExpireTime === -1 || window.siyuan.user.userSiYuanProExpireTime > 0)) { +- return false; +- } +- if (tip) { +- if (tip === window.siyuan.languages._kernel[29] && window.siyuan.config.system.container === "ios") { +- showMessage(window.siyuan.languages._kernel[122]); +- } else { +- if (tip === window.siyuan.languages._kernel[29]) { +- tip = window.siyuan.languages._kernel[29].replace("${url}", getCloudURL("subscribe/siyuan")); +- } +- showMessage(tip); +- } +- } +- return true; ++ return false + }; + + export const isPaidUser = () => { +- return window.siyuan.user && (0 === window.siyuan.user.userSiYuanSubscriptionStatus || 1 === window.siyuan.user.userSiYuanOneTimePayStatus); ++ return true + }; +diff --git a/kernel/model/cloud_service.go b/kernel/model/cloud_service.go +index 6623931..b9e03f0 100644 +--- a/kernel/model/cloud_service.go ++++ b/kernel/model/cloud_service.go +@@ -33,7 +33,6 @@ import ( + "github.com/siyuan-note/httpclient" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/conf" +- "github.com/siyuan-note/siyuan/kernel/task" + "github.com/siyuan-note/siyuan/kernel/util" + ) + +@@ -223,37 +222,7 @@ func RefreshCheckJob() { + } + + func refreshSubscriptionExpirationRemind() { +- if subscriptionExpirationReminded { +- return +- } +- subscriptionExpirationReminded = true +- +- if "ios" == util.Container { +- return +- } +- +- defer logging.Recover() + +- if IsSubscriber() && -1 != Conf.GetUser().UserSiYuanProExpireTime { +- expired := int64(Conf.GetUser().UserSiYuanProExpireTime) +- now := time.Now().UnixMilli() +- if now >= expired { // 已经过期 +- if now-expired <= 1000*60*60*24*2 { // 2 天内提醒 https://github.com/siyuan-note/siyuan/issues/7816 +- task.AppendAsyncTaskWithDelay(task.PushMsg, 30*time.Second, util.PushErrMsg, Conf.Language(128), 0) +- } +- return +- } +- remains := int((expired - now) / 1000 / 60 / 60 / 24) +- expireDay := 15 // 付费订阅提前 15 天提醒 +- if 2 == Conf.GetUser().UserSiYuanSubscriptionPlan { +- expireDay = 3 // 试用订阅提前 3 天提醒 +- } +- +- if 0 < remains && expireDay > remains { +- task.AppendAsyncTaskWithDelay(task.PushMsg, 7*time.Second, util.PushErrMsg, fmt.Sprintf(Conf.Language(127), remains), 0) +- return +- } +- } + } + + func refreshUser() { +diff --git a/kernel/model/conf.go b/kernel/model/conf.go +index 3c3add3..a095512 100644 +--- a/kernel/model/conf.go ++++ b/kernel/model/conf.go +@@ -836,22 +836,11 @@ func InitBoxes() { + } + + func IsSubscriber() bool { +- u := Conf.GetUser() +- return nil != u && (-1 == u.UserSiYuanProExpireTime || 0 < u.UserSiYuanProExpireTime) && 0 == u.UserSiYuanSubscriptionStatus ++ return true + } + + func IsPaidUser() bool { +- // S3/WebDAV data sync and backup are available for a fee https://github.com/siyuan-note/siyuan/issues/8780 +- +- if IsSubscriber() { +- return true +- } +- +- u := Conf.GetUser() +- if nil == u { +- return false +- } +- return 1 == u.UserSiYuanOneTimePayStatus ++ return true + } + + const ( +diff --git a/kernel/util/working.go b/kernel/util/working.go +index c77fe64..573ce64 100644 +--- a/kernel/util/working.go ++++ b/kernel/util/working.go +@@ -44,7 +44,7 @@ import ( + var Mode = "prod" + + const ( +- Ver = "3.1.6" ++ Ver = "100.3.1.6" + IsInsider = false + ) + diff --git a/secrets/siyuan-teidesu-authentik-env.age b/secrets/siyuan-teidesu-authentik-env.age new file mode 100644 index 0000000..c44b9ff --- /dev/null +++ b/secrets/siyuan-teidesu-authentik-env.age @@ -0,0 +1,6 @@ +age-encryption.org/v1 +-> ssh-ed25519 sj88Xw K4t0UbmCo9hVvB3k0ut17zjnN/SrqjiCRokNy4CSvi4 +b067KvwE3J3NrXY5ZANkoUdS0UTTbkWWrCpsWtS0eP8 +--- 7cx4kHSwSvsAlAMvfM/lGr3B2QhmD6vhNdFSzLAnUuo +frrx/E!~ZMTj@'EcnVsqyq