Skip to content

Commit 5379543

Browse files
author
strandedturtle
committed
Rebrand to DockPull; daily scheduled scan time; fix settings icon
- Rebrand: "Diun Updater" -> "DockPull" everywhere (UI, PWA manifest, title, README, logs), plus identifiers (cookie diun_session -> dockpull_session, storage keys diun.* -> dockpull.*, theme key, GitHub UA, default container_name + SELF_CONTAINER_NAME -> dockpull, compose service + data volume, package names). The GHCR image name is derived from the repo and is left unchanged. A couple of "you don't need Diun" notes remain by design. - Scheduler: replace the every-N-hours interval with a daily scan at a configured local time (default 09:00), mirroring a cron ping — set it to when you want your morning Discord message. setSettings re-arms it. Setting renamed backgroundCheckIntervalHours -> scheduledCheckTime (HH:MM), env CHECK_INTERVAL_HOURS -> SCHEDULED_CHECK_TIME. - Fix the malformed Settings gear icon in the mobile bottom nav. Server tests 76/76; client builds clean.
1 parent 4fc675a commit 5379543

30 files changed

Lines changed: 169 additions & 125 deletions

.env.example

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
PORT=5000
55

66
# Directory containing your docker-compose stacks. MUST be mounted at this
7-
# exact same path on the host and inside the diun-updater container (see the
7+
# exact same path on the host and inside the dockpull container (see the
88
# comment in docker-compose.yml for why).
99
STACKS_DIR=/opt/stacks
1010

@@ -32,14 +32,14 @@ BASE_URL=http://localhost:5000
3232
# --- Background checks & notifications (all optional; also editable in the UI) ---
3333
# Whether the server checks for updates on a schedule. Default: true.
3434
# BACKGROUND_CHECK_ENABLED=true
35-
# How often the background check runs, in hours (1-168). Default: 6.
36-
# CHECK_INTERVAL_HOURS=6
35+
# Daily local time (HH:MM, 24h) for the scheduled scan. Default: 09:00.
36+
# SCHEDULED_CHECK_TIME=09:00
3737
# Discord (or compatible) webhook URL to notify when updates are found.
3838
# Leave unset to disable notifications.
3939
# DISCORD_WEBHOOK_URL=
4040

4141
# Name of this app's OWN container. It is excluded from the dashboard so it
4242
# can't be told to update (and thereby restart) itself mid-update. Defaults to
43-
# "diun-updater" (the container_name in the shipped docker-compose.yml); change
43+
# "dockpull" (the container_name in the shipped docker-compose.yml); change
4444
# it only if you rename the service.
45-
SELF_CONTAINER_NAME=diun-updater
45+
SELF_CONTAINER_NAME=dockpull

API_CONTRACT.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ All request/response bodies are JSON unless noted otherwise.
1010
- Auth is a single shared password (`ADMIN_PASSWORD`), compared in constant
1111
time, no user accounts/database.
1212
- On successful login, the server sets a signed, httpOnly cookie named
13-
`diun_session` (`SameSite=Lax`, `Secure` when served over HTTPS,
13+
`dockpull_session` (`SameSite=Lax`, `Secure` when served over HTTPS,
1414
`Max-Age` = `SESSION_TTL` seconds).
1515
- Protected routes (everything except `/api/auth/login` and `/api/health`)
16-
require a valid `diun_session` cookie. If it is missing, invalid, or
16+
require a valid `dockpull_session` cookie. If it is missing, invalid, or
1717
expired, the server responds `401 Unauthorized` with
1818
`{ "error": "unauthorized" }`.
1919

@@ -24,7 +24,7 @@ All request/response bodies are JSON unless noted otherwise.
2424
- Auth: none.
2525
- Body: `{ "password": "string" }`
2626
- Response:
27-
- `200 { "ok": true }` + `Set-Cookie: diun_session=...` on success.
27+
- `200 { "ok": true }` + `Set-Cookie: dockpull_session=...` on success.
2828
- `401 { "error": "invalid_password" }` on bad password.
2929
- `429 { "error": "too_many_attempts" }` after too many failed attempts
3030
from one client IP (temporary lockout).
@@ -33,7 +33,7 @@ All request/response bodies are JSON unless noted otherwise.
3333

3434
- Auth: cookie.
3535
- Body: none.
36-
- Response: `200 { "ok": true }`, clears the `diun_session` cookie.
36+
- Response: `200 { "ok": true }`, clears the `dockpull_session` cookie.
3737

3838
### `GET /api/auth/me`
3939

@@ -63,7 +63,7 @@ All request/response bodies are JSON unless noted otherwise.
6363
- Auth: cookie.
6464
- Response: `text/event-stream` (SSE). Emits
6565
`data: {"type":"containers-changed"}` whenever server state changes (a check
66-
ran, an update finished, or a pin/hide changed) so dashboards can refresh
66+
ran, an update finished, or a pin changed) so dashboards can refresh
6767
without a manual reload. Comment lines (`: ...`) are sent as keepalives.
6868

6969
### `POST /api/update/:name`
@@ -149,7 +149,7 @@ separate section, but can still be updated by hand.
149149
"defaultFilter": "updates",
150150
"autoCheckOnOpen": true,
151151
"backgroundCheckEnabled": true,
152-
"backgroundCheckIntervalHours": 6,
152+
"scheduledCheckTime": "09:00",
153153
"discordEnabled": false,
154154
"discordWebhookUrl": ""
155155
}
@@ -158,7 +158,7 @@ separate section, but can still be updated by hand.
158158
- `autoCheckOnOpen` — whether the dashboard runs a check automatically on
159159
first open.
160160
- `backgroundCheckEnabled` — whether the server runs a scheduled check.
161-
- `backgroundCheckIntervalHours`interval for that check (1–168).
161+
- `scheduledCheckTime`daily local time (HH:MM) for the scheduled scan.
162162
- `discordEnabled` — whether to send Discord notifications on new updates.
163163
- `discordWebhookUrl` — Discord (or compatible) webhook URL, or `""`.
164164

@@ -167,7 +167,7 @@ separate section, but can still be updated by hand.
167167
- Auth: cookie.
168168
- Body: a partial patch of the settings object, e.g. `{ "defaultFilter":
169169
"all" }`. Unknown keys are ignored; invalid values for known keys return
170-
`400 { "error": "invalid_value" }`. Changing the interval/enable re-arms the
170+
`400 { "error": "invalid_value" }`. Changing the time/enable re-arms the
171171
background scheduler immediately.
172172
- Response: `200` — the full, updated settings object.
173173

README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Diun Web Updater
1+
# DockPull
22

33
A small, self-hosted, mobile-first web UI for updating Docker containers that
44
are managed by `docker compose` (e.g. via [Dockge](https://github.com/louislam/dockge)).
@@ -106,9 +106,9 @@ existing compose file (e.g. a `management` stack) and fill in the two secrets.
106106

107107
```yaml
108108
services:
109-
diun-updater:
109+
dockpull:
110110
image: ghcr.io/strandedturtle/diupdater:edge
111-
container_name: diun-updater
111+
container_name: dockpull
112112
restart: unless-stopped
113113
ports:
114114
- "5000:5000"
@@ -122,16 +122,16 @@ services:
122122
# match STACKS_DIR above, or updates fail with "compose file not found"
123123
# and relative bind mounts in your other stacks break on recreate.
124124
- /opt/stacks:/opt/stacks
125-
- diun-updater-data:/data
125+
- dockpull-data:/data
126126

127127
volumes:
128-
diun-updater-data:
128+
dockpull-data:
129129
```
130130
131131
Generate the secret (`openssl rand -hex 32`), then start just this service:
132132

133133
```bash
134-
docker compose up -d diun-updater
134+
docker compose up -d dockpull
135135
```
136136

137137
Then open `http://<host-ip>:5000`.
@@ -199,7 +199,7 @@ critical part is the **same-path stacks mount**:
199199
- /var/run/docker.sock:/var/run/docker.sock
200200
# ⚠️ SAME PATH on host and in container — do not change one side only:
201201
- ${STACKS_DIR}:${STACKS_DIR}
202-
- diun-updater-data:/data # persistent SQLite (events/history/pins)
202+
- dockpull-data:/data # persistent SQLite (events/history/pins)
203203
```
204204

205205
**Why same-path?** This app calls `docker compose` against the *host* Docker
@@ -226,10 +226,10 @@ Check it's healthy:
226226

227227
```bash
228228
curl -s http://localhost:5000/api/health # -> {"ok":true}
229-
docker logs diun-updater # -> "...server listening at ..."
229+
docker logs dockpull # -> "...server listening at ..."
230230
```
231231

232-
The SQLite database is created automatically in the `diun-updater-data` volume
232+
The SQLite database is created automatically in the `dockpull-data` volume
233233
on first start. The first time you load the UI you'll get the login screen —
234234
enter `ADMIN_PASSWORD`, and the dashboard will run an initial update check.
235235

@@ -298,17 +298,17 @@ under `errors`).
298298

299299
### Background checks & Discord notifications
300300

301-
By default the server also checks on a schedule (every 6h) so badges stay fresh
301+
By default the server runs a daily scan (09:00, server-local time) so badges stay fresh
302302
even when the app is closed. Configure it under **Settings → Background checks &
303303
Discord**:
304304

305-
- **Background checks** on/off and interval.
305+
- **Daily scan** on/off and the time of day it runs.
306306
- **Discord webhook URL** — paste a Discord channel webhook to get a message when
307307
updates are found, then use **Send test message** to verify it. Each update is
308308
announced once (no repeats on every check).
309309

310310
These can also be seeded from the environment (`BACKGROUND_CHECK_ENABLED`,
311-
`CHECK_INTERVAL_HOURS`, `DISCORD_WEBHOOK_URL`); the Settings UI overrides at
311+
`SCHEDULED_CHECK_TIME`, `DISCORD_WEBHOOK_URL`); the Settings UI overrides at
312312
runtime.
313313

314314
---
@@ -328,9 +328,9 @@ All configuration is via environment variables (see `.env.example`).
328328
| `SESSION_TTL` | `604800` | | Login cookie lifetime in seconds (7 days). |
329329
| `BASE_URL` | `http://localhost:5000` | | Public URL; if `https`, the cookie is set `Secure`. |
330330
| `DISCORD_WEBHOOK_URL` | — | | Discord webhook for update notifications (optional; also set in Settings). |
331-
| `CHECK_INTERVAL_HOURS` | `6` | | Background check interval in hours (1–168). |
331+
| `SCHEDULED_CHECK_TIME` | `09:00` | | Daily local time (HH:MM) for the scheduled scan. |
332332
| `BACKGROUND_CHECK_ENABLED` | `true` | | Whether the scheduled background check runs. |
333-
| `SELF_CONTAINER_NAME` | `diun-updater` | | This app's own container name, excluded from the dashboard so it can't update itself. |
333+
| `SELF_CONTAINER_NAME` | `dockpull` | | This app's own container name, excluded from the dashboard so it can't update itself. |
334334

335335
The two required vars are enforced at startup — the server refuses to boot
336336
without them (a `SKIP_CONFIG_CHECK=1` escape hatch exists for skeleton
@@ -354,7 +354,7 @@ smoke-tests only; never use it in production).
354354
open internet or fronting it with Cloudflare Access if exposure matters.
355355
- **The app excludes its own container** from the dashboard (it can't safely
356356
update itself). Update the updater the normal way:
357-
`docker compose pull diun-updater && docker compose up -d diun-updater`.
357+
`docker compose pull dockpull && docker compose up -d dockpull`.
358358

359359
---
360360

@@ -381,7 +381,7 @@ quay.io work.
381381
pending event automatically (this also covers multi-arch images, where the
382382
registry digest and the running digest legitimately differ). If a badge sticks,
383383
tap **Check for updates** again; if it persists, there may be a genuinely newer
384-
image — check the History tab and `docker logs diun-updater`.
384+
image — check the History tab and `docker logs dockpull`.
385385

386386
**Can't log in / cookie not sticking.** If you're on `https`, make sure
387387
`BASE_URL` is your `https://` URL (otherwise the `Secure` cookie won't be set
@@ -430,5 +430,5 @@ cd client && npm run build # production bundle -> client/dist/
430430
Build the production image manually (build context must be the repo root):
431431

432432
```bash
433-
docker build -f server/Dockerfile -t diun-updater .
433+
docker build -f server/Dockerfile -t dockpull .
434434
```

client/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<meta name="mobile-web-app-capable" content="yes" />
88
<meta name="apple-mobile-web-app-capable" content="yes" />
99
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
10-
<meta name="apple-mobile-web-app-title" content="Diun Updater" />
10+
<meta name="apple-mobile-web-app-title" content="DockPull" />
1111
<link rel="apple-touch-icon" href="/icon-192.png" />
1212
<link rel="manifest" href="/manifest.webmanifest" />
13-
<title>Diun Updater</title>
13+
<title>DockPull</title>
1414
</head>
1515
<body>
1616
<div id="root"></div>

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "diun-updater-client",
2+
"name": "dockpull-client",
33
"version": "0.1.0",
44
"private": true,
55
"license": "MIT",

client/src/AuthPage.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default function AuthPage({ onAuthed }) {
2828
return (
2929
<div className="auth-page">
3030
<div className="auth-card">
31-
<h1>Diun Updater</h1>
31+
<h1>DockPull</h1>
3232
<p className="subtitle">Sign in to manage your containers</p>
3333
<form onSubmit={handleSubmit}>
3434
<div className="field">

client/src/Dashboard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import UpdateCard from './components/UpdateCard.jsx';
44
import UpdateAllButton from './components/UpdateAllButton.jsx';
55
import StackGroup from './components/StackGroup.jsx';
66

7-
const AUTOCHECK_SESSION = 'diun.autochecked';
7+
const AUTOCHECK_SESSION = 'dockpull.autochecked';
88
const UNGROUPED = 'Ungrouped';
99

1010
function hasUpdate(c) {

client/src/components/BottomNav.jsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,19 @@ const HistoryIcon = () => (
2323
);
2424

2525
const SettingsIcon = () => (
26-
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
27-
<circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="2" />
28-
<path
29-
d="M19.4 13a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-.33-1.82l-1-1a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 01-1.82-.33l-.06-.06a1.65 1.65 0 01-.33-1.82V5a1.65 1.65 0 00-1.65-1.65h-1.4A1.65 1.65 0 009.7 5v.1a1.65 1.65 0 01-.33 1.82 1.65 1.65 0 01-1.82.33l-.06-.06a1.65 1.65 0 00-1.82.33l-1 1a1.65 1.65 0 00-.33 1.82 1.65 1.65 0 01.33 1.82l-.06.06a1.65 1.65 0 00-.33 1.82l1 1a1.65 1.65 0 001.82.33 1.65 1.65 0 011.82.33l.06.06a1.65 1.65 0 01.33 1.82V19A1.65 1.65 0 0011 20.65h1.4A1.65 1.65 0 0014 19v-.1a1.65 1.65 0 01.33-1.82 1.65 1.65 0 011.82-.33l.06.06a1.65 1.65 0 001.82-.33l1-1a1.65 1.65 0 00.33-1.82z"
30-
stroke="currentColor"
31-
strokeWidth="1.5"
32-
strokeLinecap="round"
33-
strokeLinejoin="round"
34-
/>
26+
<svg
27+
width="22"
28+
height="22"
29+
viewBox="0 0 24 24"
30+
fill="none"
31+
stroke="currentColor"
32+
strokeWidth="2"
33+
strokeLinecap="round"
34+
strokeLinejoin="round"
35+
aria-hidden="true"
36+
>
37+
<circle cx="12" cy="12" r="3" />
38+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
3539
</svg>
3640
);
3741

client/src/components/Header.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export default function Header({ pendingCount = 0, onLoggedOut }) {
6666
return (
6767
<header className="app-header">
6868
<Link to="/" className="title-link">
69-
<span>Diun Updater</span>
69+
<span>DockPull</span>
7070
{pendingCount > 0 && <span className="badge">{pendingCount}</span>}
7171
</Link>
7272
<nav className="header-nav" aria-label="Primary">

client/src/components/StackGroup.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const Chevron = ({ open }) => (
2626
* - children: the cards
2727
*/
2828
export default function StackGroup({ title, count, updateCount = 0, storageKey, defaultOpen = true, children }) {
29-
const key = `diun.group.${storageKey}`;
29+
const key = `dockpull.group.${storageKey}`;
3030
const [open, setOpen] = useState(() => {
3131
try {
3232
const stored = localStorage.getItem(key);

0 commit comments

Comments
 (0)