7 Commits

Author SHA1 Message Date
Krzysztof
b2d535d885 build only on release 2025-08-03 14:44:39 +02:00
Krzysztof
daf27255d6 update docker hub image 2025-08-03 14:40:59 +02:00
Krzysztof
f2f24532ed add docker build 2025-08-03 14:37:12 +02:00
Krzysztof
2adbc0b073 update docker readme 2025-08-03 14:24:01 +02:00
Krzysztof
50a46d8ad9 add docker files 2025-08-03 14:20:47 +02:00
Krzysztof
17cabd68ad add docs 2025-08-03 12:51:56 +02:00
Krzysztof
1db65385ce update footer links 2025-08-03 12:30:04 +02:00
13 changed files with 194 additions and 37 deletions

47
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Docker
on:
release:
types: [published]
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: airlabs/uptimemonitor
- name: Build and push Docker image
id: push
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: index.docker.io/airlabs/uptimemonitor
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

24
Dockerfile Normal file
View File

@@ -0,0 +1,24 @@
FROM golang:latest AS builder
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -o uptimemonitor \
-ldflags "-X uptimemonitor/pkg/version.Version=$(git describe --tags)" \
./cmd/uptimemonitor
FROM alpine:latest
WORKDIR /app
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/uptimemonitor .
EXPOSE 3000
CMD ["./uptimemonitor"]

View File

@@ -1,7 +1,106 @@
# UPTIME MONITOR
![](/docs/uptimemonitor.png)
[![Go](https://github.com/airlabspl/uptimemonitor/actions/workflows/go.yml/badge.svg)](https://github.com/airlabspl/uptimemonitor/actions/workflows/go.yml)
[uptimemonitor.dev](https://uptimemonitor.dev)
© 2025 AIR Labs
## Yet another uptime monitor?
Yes, but with following constraints:
- 100% self-hosted
- Single binary when build
- 0 configuration
- Simple functionality without bloat
## Installation
1. Download the latest release to a Linux VPS (check the
[Releases page](https://github.com/airlabspl/uptimemonitor/releases)):
```bash
wget https://github.com/airlabspl/uptimemonitor/releases/download/v0.0.2-alpha/uptimemonitor
chmod +x uptimemonitor
```
2. Run it
```bash
./uptimemonitor -addr=":3000"
```
You can also use provided `Dockerfile` and `docker-compose.yml` for reference to
run the app using Docker.
For example, to run a local copy without https enabled:
```bash
SECURE=false COOLIFY_VOLUME_APP=~/testdata docker-compose up
```
## First run
When you first run the application you will be asked to create a new account,
which you will then use to log in.
![](/docs/setup.png)
## Usage
To start monitoring a given url, add the url on a `/new` page. You can specify
the HTTP method the check will use (GET, POST, etc.) as well as add custom
headers and body to the request.
![](/docs/new.png)
## Incidents
When the check fails, the incident will be created and will stay open until the
upcoming check succeeds. You can dig into the failing request details on a
incident page.
![](/docs/incident.png)
## Webhooks
If you want to get notified when an incident happens, you can also configure a
webhook notification to a given url of choice (e.g. slack or google chat webhook
url). You can use `{{ .Url }}` and `{{ .StatusCode }}` variables inside a body
to pass those information to the webhook.
![](/docs/webhook.png)
## Https
Because the app uses secure cookies for authentication, it is required to use
some reverse proxy with https certificate configured.
If you want to test the app without secure cookies enabled, provide the
`-secure=false` flag.
## Backups
This app uses a sqlite database so to backup the data just copy the
`uptimemonitor.sqlite*` files to a new location.
## Pricing
The app is free to use but if you are using it commercially and can aford a
small donation- please use Github Sponsors.
The donations of $50 a month and above will be featured in a sponsors area
inside the application dashboard.
## Roadmap
- Monitor status badges
- Change password
- Manage users
- Timezones
- Reset password via cli
- Add "Test Webhook" button with fake incident
- Sort monitors option (with localstorage sync) by created_at/name(domain)

29
TODO.md
View File

@@ -1,29 +0,0 @@
# TODO
What's left to do:
- [ ] Get app version from git tag
- [ ] Add documentation
- [ ] Document how to install
- [ ] Document webhook parsing and available variables
- [ ] Release 🎉
Optional:
- [ ] Monitor status
- [ ] Change password
- [ ] Add users
- [ ] Remove users
- [ ] Change user passwords
- [ ] Timezones
- [ ] Reset password via cli
- [ ] Use the same form for creation and editing of monitor
- [ ] Save check response
- [ ] Add check response modal (div#modals + append when clicked + destroy when
clicked)
- [ ] Mobile breadcrumbs (dropdown/select)
- [ ] Add "Test Webhook" button with fake incident
- [ ] Sort monitors option (with localstorage sync) by created_at/name(domain)
- [ ] Session expiration
- [ ] Test check timeout
- [ ] Loading placeholders (skeletons)

View File

@@ -23,12 +23,16 @@ var (
)
func main() {
flag.StringVar(&dsn, "dsn", "uptimemonitor.sqlite?_journal_mode=WAL&_busy_timeout=5000&_synchronous=FULL&_txlock=immediate", "database server name")
flag.StringVar(&dsn, "dsn", "data/uptimemonitor.sqlite?_journal_mode=WAL&_busy_timeout=5000&_synchronous=FULL&_txlock=immediate", "database server name")
flag.StringVar(&addr, "addr", ":3000", "server address")
flag.BoolVar(&secure, "secure", true, "use https")
flag.Parse()
if os.Getenv("SECURE") == "false" {
secure = false
}
store := store.New(dsn)
service := service.New(store)
handler := handler.New(store, service, secure)

2
data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

15
docker-compose.yml Normal file
View File

@@ -0,0 +1,15 @@
# documentation: https://github.com/airlabspl/uptimemonitor/blob/master/README.md
# slogan: A self-hosted, simple web uptime monitor
# tags: uptime,downtime,monitor,self-hosted
# logo: svgs/uptime-monitor-dev.svg
# port: 3000
services:
app:
image: airlabs/uptimemonitor:master
environment:
- SECURE=${SECURE}
ports:
- "3000:3000"
restart: always
volumes:
- ${COOLIFY_VOLUME_APP}:/app/data

BIN
docs/incident.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
docs/new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
docs/setup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/uptimemonitor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/webhook.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -39,20 +39,15 @@
<footer class="text-sm text-base-content p-4 flex flex-col md:flex-row gap-12 md:gap-4">
<nav class="flex flex-col gap-2 flex-1">
<h6 class="footer-title truncate">{{ .User.Name }}</h6>
<a class="link link-hover">Account settings</a>
<a class="link link-hover">Manage users</a>
<a class="link link-hover" href="/logout">Log out</a>
</nav>
<nav class="flex flex-col gap-2 flex-1">
<h6 class="footer-title">UPTIMEMONITOR</h6>
<a class="link link-hover">Documentation</a>
<a class="link link-hover">Pricing</a>
<a class="link link-hover">Terms of use</a>
<a class="link link-hover" href="https://github.com/airlabspl/uptimemonitor/blob/master/README.md"
target="_blank" rel="noopener noreferrer">Documentation</a>
</nav>
<nav class="flex flex-col gap-2 flex-1">
<h6 class="footer-title">AIR Labs</h6>
<a class="link link-hover">About us</a>
<a class="link link-hover">Other products</a>
<a class="link link-hover flex items-center gap-1" href="https://x.com/airlabspl" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" version="1.1" class="size-[11px]!">
<path