lyc8503 / UptimeFlare

✔ Free and serverless uptime monitoring / status page on Cloudflare Workers, with Geo-specific checks
Apache License 2.0
830 stars 87 forks source link

Selfhost #22

Open Its4Nik opened 1 month ago

Its4Nik commented 1 month ago

I know this isn't the designed usecase.

But might it be possible to run this inside a docker container?

I would love to help but im not sure how Cloudflare Workers work

Its4Nik commented 1 month ago

I know this isn't the designed usecase.

But might it be possible to run this inside a docker container?

I would love to help but im not sure how Cloudflare Workers work

i want to add that the interface looks really good, props to you!

lyc8503 commented 1 month ago

i want to add that the interface looks really good, props to you!

Thanks for the compliment! 😂

This seems a duplicate for #14 (sorry for simplified Chinese)

That's definitely not how it's expected to work, but if you have a valid reason to self-host this project instead of uptime-kuma (which is more feature-rich as it's run on native platforms instead of Workers), there is a method:

Cloudflare wrangler has a built-in workerd that allows you to run workers and pages locally, in fact, you can try to package a container image using wrangler.

I used this method for another project: https://github.com/lyc8503/onedrive-cf-index-ng

I may try to write a dockerfile when I have time, you can also try it yourself, if you configure it successfully, PRs are always welcome.

Its4Nik commented 1 month ago

i want to add that the interface looks really good, props to you!

Thanks for the compliment! 😂

This seems a duplicate for #14 (sorry for simplified Chinese)

That's definitely not how it's expected to work, but if you have a valid reason to self-host this project instead of uptime-kuma (which is more feature-rich as it's run on native platforms instead of Workers), there is a method:

Cloudflare wrangler has a built-in workerd that allows you to run workers and pages locally, in fact, you can try to package a container image using wrangler.

I used this method for another project: https://github.com/lyc8503/onedrive-cf-index-ng

I may try to write a dockerfile when I have time, you can also try it yourself, if you configure it successfully, PRs are always welcome.

Oh, yeah I am absolutely going to try that, and yeah I didn't see that because its simplified Chinese.

Would you mind sharing your discord or some other platform if I have questions? Or should I Just keep opening issues if there are some?

lyc8503 commented 1 month ago

Sorry I don't use discord very often, but if you don't feel comfortable communicating in issues, you can also send me e-mails: me@lyc8503.site

Its4Nik commented 1 month ago

yeah im definitely going to do that, but i am some how lost i cant find any dependecies and on what port this service runs, i guess 80. Do you have some sort of internal documentation?

lyc8503 commented 1 month ago

yeah im definitely going to do that, but i am some how lost i cant find any dependecies and on what port this service runs, i guess 80. Do you have some sort of internal documentation?

I don't have any internal docs. Maybe you can refer to https://developers.cloudflare.com/workers/wrangler/commands/#dev.

I thought last time I got it to work just by installing wrangler and referring to its --help.

Its4Nik commented 1 month ago

yeah im definitely going to do that, but i am some how lost i cant find any dependecies and on what port this service runs, i guess 80. Do you have some sort of internal documentation?

I don't have any internal docs. Maybe you can refer to https://developers.cloudflare.com/workers/wrangler/commands/#dev.

I thought last time I got it to work just by installing wrangler and referring to its --help.

Ah okay Im reading through it right now, are there any sort of dependecies used? Idk like wget or curl or something like that?

Its4Nik commented 1 month ago

@lyc8503 I'm getting a constant 405 Method not allowed as far as i can see its this line

    if (request.method !== 'POST') {
      return new Response('Remote worker is working...', { status: 405 })
    }

also no console logs image image

Its4Nik commented 1 month ago

nvm forgot to build the project 😭

Its4Nik commented 1 month ago

@lyc8503 do you have some sort of .dev.vars file? Wrangler throws me that Error.

This is my Dockerfile:

# Use Node.js 20 Alpine as base image
FROM node:20-alpine AS base

# Update package index
RUN apk update

# Create directories
RUN mkdir -p /app && \
    mkdir -p /tmp/package

# Copy package.json files to /tmp/package/
COPY ./data/package*.json /tmp/package/

# Change working directory to /tmp/package/ and install wrangler globally and npm packages
RUN cd /tmp/package && \
    npm install -g wrangler@latest && \
    npm install

# Set working directory to /app
WORKDIR /app

# Create a .env file
RUN touch /app/.env

# Copy the application code to /app
COPY ./data /app # ./data is just the entire repo for now

# Define volume for /app
VOLUME [ "/app" ]

# Expose port 9999
EXPOSE 9999

# Set the default command to run the development server
CMD ["wrangler", "dev", "-c", "worker/wrangler-dev.toml", "--node-compat", "--port", "9999", "--log-level", "debug"]

And this is the error:

Failed to load .env file "/app/worker/.dev.vars": Error: ENOENT: no such file or directory, open '/app/worker/.dev.vars'
    at Object.openSync (node:fs:573:18)
    at Object.readFileSync (node:fs:452:35)
    at tryLoadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:158864:72)
    at loadDotEnv (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:158873:12)
    at getVarsForDev (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:197634:18)
    at getBindings (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:205523:10)
    at getBindingsAndAssetPaths (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:205404:20)
    at getDevReactElement (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:205076:40)
    at startDev (/usr/local/lib/node_modules/wrangler/wrangler-dist/cli.js:205140:60)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/app/worker/.dev.vars'
lyc8503 commented 1 month ago

Sorry, I'm not sure what this file is, this should be a wrangler issue, you may need to google it. If wrangler is working on your host, there should be no reason why it doesn't work/need extra files in the container, you might want to check args, workdir, environment variables or something like that.

Its4Nik commented 1 month ago

mhh okay i was already looking around, but hey i made a lot of progress in my opinion :D And sooner or late it'll work

Edit: current help for this is found here: https://discord.com/channels/595317990191398933/1240726123034316942

Its4Nik commented 1 month ago
docker run --name test --rm -p 9999:9999 uptimeflare:latest
 ⛅️ wrangler 3.57.0
-------------------
▲ [WARNING] --local is no longer required and will be removed in a future version.

  `wrangler dev` now uses the local Cloudflare Workers runtime by default. 🎉

▲ [WARNING] Enabling Node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.

Your worker has access to the following bindings:
- KV Namespaces:
  - UPTIMEFLARE_STATE: UPTIMEFLARE_STATE
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:9999
⎔ Reloading local server...

Got it to work (kinda) the website won't load tho gonna look into it later

Its4Nik commented 1 month ago

@lyc8503 maybe you know what this is, I don't have a clue about GO.

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
github.com/evanw/esbuild/internal/helpers.(*ThreadSafeWaitGroup).Wait(...)
        github.com/evanw/esbuild/internal/helpers/waitgroup.go:36
main.runService.func2()
        github.com/evanw/esbuild/cmd/esbuild/service.go:114 +0x59
main.runService(0x1)
        github.com/evanw/esbuild/cmd/esbuild/service.go:160 +0x4ed
main.main()
        github.com/evanw/esbuild/cmd/esbuild/main.go:236 +0xa29

goroutine 6 [chan receive]:
main.runService.func1()
        github.com/evanw/esbuild/cmd/esbuild/service.go:98 +0x4a
created by main.runService
        github.com/evanw/esbuild/cmd/esbuild/service.go:97 +0x1e5

goroutine 7 [chan receive]:
main.(*serviceType).sendRequest(0xc000023e60, {0x8ee6e0, 0xc000439fb0})
        github.com/evanw/esbuild/cmd/esbuild/service.go:192 +0xfa
main.runService.func3()
        github.com/evanw/esbuild/cmd/esbuild/service.go:125 +0x39
created by main.runService
        github.com/evanw/esbuild/cmd/esbuild/service.go:122 +0x31c

goroutine 30 [semacquire]:
sync.runtime_Semacquire(0xc0005327c8?)
        runtime/sema.go:62 +0x27
sync.(*WaitGroup).Wait(0x0?)
        sync/waitgroup.go:116 +0x4b
github.com/evanw/esbuild/internal/bundler.ScanBundle({_, _, _, _, _, _}, {_, _}, _, {0xc0002ff440, ...}, ...)
        github.com/evanw/esbuild/internal/bundler/bundler.go:1208 +0x948
github.com/evanw/esbuild/pkg/api.rebuildImpl({0xc000252de0, {0xc0002c0270, 0x1, 0x1}, {0x0, 0x0, 0x0}, {0x0, 0x1, 0x0, ...}, ...}, ...)
        github.com/evanw/esbuild/pkg/api/api_impl.go:1483 +0x2ca
github.com/evanw/esbuild/pkg/api.(*internalContext).rebuild(_)
        github.com/evanw/esbuild/pkg/api/api_impl.go:1020 +0x27f
github.com/evanw/esbuild/pkg/api.(*internalContext).Watch.func1()
        github.com/evanw/esbuild/pkg/api/api_impl.go:1101 +0x2e
github.com/evanw/esbuild/pkg/api.(*watcher).start.func1()
        github.com/evanw/esbuild/pkg/api/watcher.go:109 +0x106
created by github.com/evanw/esbuild/pkg/api.(*watcher).start
        github.com/evanw/esbuild/pkg/api/watcher.go:82 +0x8a

goroutine 285 [chan send]:
github.com/evanw/esbuild/internal/bundler.ScanBundle.func2()
        github.com/evanw/esbuild/internal/bundler/bundler.go:1162 +0x2c5
created by github.com/evanw/esbuild/internal/bundler.ScanBundle
        github.com/evanw/esbuild/internal/bundler/bundler.go:1160 +0x93b

goroutine 283 [chan receive]:
main.(*serviceType).sendRequest(0xc000023e60, {0x8ee6e0, 0xc0004b9530})
        github.com/evanw/esbuild/cmd/esbuild/service.go:192 +0xfa
main.(*serviceType).convertPlugins.func2.2()
        github.com/evanw/esbuild/cmd/esbuild/service.go:936 +0x113
github.com/evanw/esbuild/pkg/api.(*pluginImpl).onStart.func1()
        github.com/evanw/esbuild/pkg/api/api_impl.go:1880 +0x42
github.com/evanw/esbuild/internal/bundler.ScanBundle.func1({{0x964f83, 0x12}, {0xc0002c01f8, 0x1, 0x1}, {0xc000287a10, 0x1, 0x1}, {0xc000287a70, 0x1, ...}}, ...)
        github.com/evanw/esbuild/internal/bundler/bundler.go:1131 +0x6a
created by github.com/evanw/esbuild/internal/bundler.ScanBundle
        github.com/evanw/esbuild/internal/bundler/bundler.go:1130 +0xf3d
lyc8503 commented 1 month ago

@lyc8503 maybe you know what this is, I don't have a clue about GO.

Sorry I don't know what this is, I can only tell by the error message that this seems to be a problem with esbuild, how did you come across this error?

Also, in Docker containers you may need to listen on 0.0.0.0 before you can use -p for port forwarding.

Its4Nik commented 1 month ago

@lyc8503 maybe you know what this is, I don't have a clue about GO.

Sorry I don't know what this is, I can only tell by the error message that this seems to be a problem with esbuild, how did you come across this error?

Also, in Docker containers you may need to listen on 0.0.0.0 before you can use -p for port forwarding.

AFAIK if there is only -p it defaults to 0.0.0.0

I can provide the wrangler dev command here:

CMD ["wrangler", "dev", "--local", "-c", "worker/wrangler-dev.toml", "--node-compat", "--port", "9999", "--log-level", "log"] Or: wrangler dev --local -c worker/wrangler-dev.toml --node-compat --port 9999 --log-level log

Its4Nik commented 1 month ago

@lyc8503 maybe you know what this is, I don't have a clue about GO.

Sorry I don't know what this is, I can only tell by the error message that this seems to be a problem with esbuild, how did you come across this error?

I just ran the container with this dockerfile:

# Use Node.js 20 Alpine as base image
FROM node:slim

# Create and set the working directory
WORKDIR /app

# Copy the application code to the working directory
COPY ./data /app # ./data is just the whole UptimeFlare Repository 

# Install global npm packages and local dependencies
RUN npm install -g npm wrangler

# Create a .env file
RUN touch .env

# Define volume for /app
VOLUME [ "/app" ]

# Expose port 9999
EXPOSE 9999

# Set the default command to run the development server
CMD ["wrangler", "dev", "--local", "-c", "worker/wrangler-dev.toml", "--node-compat", "--port", "9999", "--log-level", "log"]

And ran with this command: docker run --name test --rm -p 9999:9999 uptimeflare:latest

Its4Nik commented 1 month ago

Sorry, I'm not sure what this file is, this should be a wrangler issue, you may need to google it. If wrangler is working on your host, there should be no reason why it doesn't work/need extra files in the container, you might want to check args, workdir, environment variables or something like that.

And btw. this was just an info message the .dev.vars file isn't needed, its optional (still no clue what it's used for)

Its4Nik commented 1 month ago

(sry for the spam btw)

Your worker has access to the following bindings:
- KV Namespaces:
  - UPTIMEFLARE_STATE: UPTIMEFLARE_STATE
⎔ Starting local server...
✘ [ERROR] service core:user:uptimeflare_worker: Uncaught SyntaxError: Unexpected token 'export'

    at null.<anonymous> (index.ts:6)

✘ [ERROR] MiniflareCoreError [ERR_RUNTIME_FAILURE]: The Workers runtime failed to start. There is likely additional logging output above.

This was achieved using wrangler dev --local -c worker/wrangler-dev.toml --no-bundle --node-compat --port 9999 --log-level log

I am not really sure how typescript works, but this seems to be the problem.

Its4Nik commented 1 month ago

index.ts

export interface Env {
  UPTIMEFLARE_STATE: KVNamespace
}

this seems to be the part where the problem occured.

I don't know how typescript works but it seems running the export function locally is some sort of error, so maybe adding a check if wrangler is running locally?