Skip to content

Commit 8131397

Browse files
committed
feat: add secure responsive config UI and repository activity
Add one-time owner registration, form login, expiring sessions and password-confirmed account and storage changes. Introduce a guided black-and-white config interface with light and dark themes, mobile layouts, optional Kuma settings and the latest 250 repository results. Harden forms, secret handling and browser security headers; update deployment documentation and tests.
1 parent a872d30 commit 8131397

23 files changed

Lines changed: 2349 additions & 239 deletions

‎.env.example‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Deployment target: Ubuntu 24.04+ x86_64; compose.yaml fixes linux/amd64.
22
# Required values must be available to Coolify Compose build-time interpolation AND runtime.
33
# Automatic GitHub App setup (default): no App ID, PEM, or Base64 to copy.
4-
# REQUIRED for browser setup: the exact HTTPS origin assigned to github-setup in Coolify.
4+
# REQUIRED for browser configuration: the exact HTTPS origin assigned to github-config in Coolify.
55
# Example: https://github-backup.example.com (no path, no trailing slash).
6-
GITHUB_SETUP_URL=
7-
# REQUIRED for browser setup: create a unique random password with: openssl rand -hex 32
8-
# Login username is admin. Keep this value masked and independent of GitHub credentials.
9-
GITHUB_SETUP_PASSWORD=
10-
# Everything else needed for GitHub/Spaces is entered in the protected setup page.
6+
GITHUB_CONFIG_URL=
7+
# First visit: register a username and password with the one-time code retrieved in
8+
# the github-config service terminal: python -m github_backup.config_auth registration-code
9+
# No password environment variable. Registration closes permanently after first use.
10+
# GitHub/Spaces and optional Uptime Kuma are configured in the protected config page.
1111
# Setup defaults: Spaces region=fra1, root folder=github-backup.
1212
# OPTIONAL: scheduler, retention, capacity and monitoring defaults.
1313
BACKUP_INTERVAL_HOURS=1
@@ -28,15 +28,16 @@ BACKUP_MEMORY_LIMIT=512m
2828
# Optional comma-separated numeric IDs of intentionally deleted repos; never purges data.
2929
ACKNOWLEDGED_MISSING_REPOSITORIES=
3030

31-
# OPTIONAL: disabled when empty. Copy a Push monitor's secret URL from Uptime Kuma.
31+
# OPTIONAL legacy Kuma fallback: prefer the config-page form. Saved settings take precedence.
32+
# Disabled when empty; paste a Push monitor's secret URL if using the env alternative.
3233
UPTIME_KUMA_PUSH_URL=
3334
# Enable only for Kuma reached over a trusted private HTTP network.
3435
UPTIME_KUMA_ALLOW_HTTP=false
3536
UPTIME_KUMA_TIMEOUT_SECONDS=5
3637
# 0 = automatic: 2 * BACKUP_INTERVAL_HOURS + 1 (3 hours with default hourly checks).
3738
UPTIME_KUMA_MAX_SUCCESS_AGE_HOURS=0
3839

39-
# OPTIONAL manual alternative: leave all three empty for browser setup.
40+
# OPTIONAL manual alternative: leave all three empty for browser configuration.
4041
# GitHub App General > App ID; install on All repositories for each listed login.
4142
# Private keys > Generate a private key; base64 < app-private-key.pem | tr -d '\n'
4243
# Manual settings take precedence over saved browser credentials; use one mode.

‎.github/workflows/ci.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ jobs:
7373
github-backup:ci --version
7474
docker run --rm --platform linux/amd64 --read-only --cap-drop=ALL --security-opt=no-new-privileges \
7575
github-backup:ci help run
76-
- name: Smoke-test protected setup server
76+
- name: Smoke-test protected config server
7777
run: |
78-
docker run --detach --name github-backup-setup-ci --platform linux/amd64 \
78+
docker run --detach --name github-backup-config-ci --platform linux/amd64 \
7979
--read-only --cap-drop=ALL --security-opt=no-new-privileges \
8080
--tmpfs /tmp:rw,noexec,nosuid,size=16m \
8181
--entrypoint gunicorn github-backup:ci \
8282
--bind 0.0.0.0:8080 --workers 1 --threads 2 --worker-tmp-dir /tmp \
83-
github_backup.onboarding:application
84-
trap 'docker rm --force github-backup-setup-ci' EXIT
83+
github_backup.config_web:application
84+
trap 'docker rm --force github-backup-config-ci' EXIT
8585
for attempt in $(seq 1 20); do
86-
if docker exec github-backup-setup-ci python -c \
86+
if docker exec github-backup-config-ci python -c \
8787
"import urllib.request; assert urllib.request.urlopen('http://127.0.0.1:8080/health', timeout=2).read() == b'OK'"; then
8888
exit 0
8989
fi
9090
sleep 1
9191
done
92-
docker logs github-backup-setup-ci
92+
docker logs github-backup-config-ci
9393
exit 1

‎README.md‎

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,40 @@ issues, Actions artifacts, secrets, or submodule contents from other repositorie
3737
1. Add `https://github.com/drhdev/github-backup` using the **Docker Compose** build strategy.
3838
Set Base Directory to `/` and Docker Compose Location to `/compose.yaml`.
3939
2. Keep one replica of each service and the persistent `backup-cache` volume.
40-
3. Assign an **HTTPS domain to `github-setup`, target port 8080**. If Coolify encodes
40+
3. Assign an **HTTPS domain to `github-config`, target port 8080**. If Coolify encodes
4141
the target port in its domain field, use `https://github-backup.example.com:8080`.
4242
The external URL remains `https://github-backup.example.com` on port 443.
4343
Leave `github-backup` without a domain or published port.
4444
4. **Disable automatic deployments, previews, and overlapping/rolling replacements.**
45-
5. Set just these two required environment variables, keep the password masked, and deploy:
45+
5. Set the required config URL and deploy:
4646

4747
```dotenv
48-
GITHUB_SETUP_URL=https://github-backup.example.com
49-
GITHUB_SETUP_PASSWORD=REPLACE_WITH_OUTPUT_OF_OPENSSL_RAND_HEX_32
48+
GITHUB_CONFIG_URL=https://github-backup.example.com
5049
```
5150

52-
Generate the password with `openssl rand -hex 32`. The URL must be the exact external HTTPS
53-
origin without a path or internal `:8080` suffix. Enable Buildtime and Runtime for supplied
54-
values in Coolify. No Spaces credentials, bucket settings, GitHub App IDs or PEMs need to
55-
be entered in the environment. See [the deployment guide](docs/COOLIFY.md).
51+
The URL is the exact external HTTPS origin without a path or internal `:8080` suffix.
52+
Enable Buildtime and Runtime in Coolify. No password, Spaces credentials, App IDs or PEMs
53+
need to be entered in the environment.
5654

57-
### 2. Configure DigitalOcean Spaces in the setup page
55+
On the first visit, the page shows **Create your config account**. In Coolify, open the
56+
**`github-config` service Terminal** and retrieve its one-time registration code:
5857

59-
Open the setup URL and log in as **admin** with your setup password. Enter:
58+
```bash
59+
python -m github_backup.config_auth registration-code
60+
```
61+
62+
Enter that code, choose your username and a unique **16-128 character password/passphrase**,
63+
confirm it, and save the credentials in your password manager. Then use the login form.
64+
The code prevents someone else from claiming an unregistered deployment. Registration closes
65+
permanently after the first account is created; later visits show login, with a logout button
66+
inside setup. **There is no password-reset or second-registration feature.** Forgotten
67+
credentials require a fresh deployment with a new persistent volume; existing S3 backups
68+
are preserved. Missing/corrupt authentication files block access instead of reopening registration.
69+
See [authentication and recovery](docs/GITHUB_APP.md#config-account-and-recovery).
70+
71+
### 2. Configure DigitalOcean Spaces in the config page
72+
73+
After registering and logging in with your chosen username, enter:
6074

6175
| Setup field | Where to get it |
6276
|---|---|
@@ -102,6 +116,22 @@ Optional scheduling, capacity, retention and monitoring settings retain the defa
102116
[.env.example](.env.example). Existing manual environment deployments remain supported;
103117
saved browser Spaces settings take precedence over their legacy Spaces variables.
104118

119+
### Edit configuration and review activity
120+
121+
The **Config** page follows three steps: **1. Storage → 2. GitHub connections → 3. Repository scope**.
122+
Configured sections collapse; click their heading to reopen and edit. Saved secrets are never
123+
shown or prefilled. Editing saved storage requires your current password. Use **Monitoring** for optional Kuma settings. The interface uses a neutral
124+
black-and-white design, automatic light/dark mode and a theme selector, with mobile touch targets.
125+
126+
Open **Account** to change your username or password. Confirm your current password; changing
127+
either signs out all browsers without affecting backups or reopening registration.
128+
129+
Open **Activity** to view/search the last **250 completed repository checks**, including status,
130+
completion time and duration, in pages of 25. Times adapt to the browser's time zone; UTC remains
131+
available in the timestamp title. Unchanged successful checks are included. History starts when
132+
this feature is deployed; older remote manifests are not imported. This local bounded log contains
133+
no credentials, raw exception messages or Git URLs and never blocks backups if history storage fails.
134+
105135
### 4. Verify the first backup
106136

107137
Open the Coolify logs. A successful run emits `backup_finished` with `exit_code: 0`.
@@ -139,7 +169,7 @@ it cannot fit a new artifact, it fails visibly rather than delete protected reco
139169

140170
## Docker logs and monitoring
141171

142-
Application diagnostics are JSON on **stderr**; scheduler/run events are JSON on **stdout**.
172+
Backup diagnostics are JSON on **stderr**; scheduler/run events are JSON on **stdout**.
143173
Docker and Coolify collect both streams. No application log files or log-volume mounts are required.
144174
Compose rotates Docker logs at **10 MB × 3 files**. Locally:
145175

@@ -152,18 +182,17 @@ repositories, or stale checks become unhealthy. Docker's restart policy does not
152182
container solely for being unhealthy; configure notifications and inspect the logs.
153183

154184
**Optional Uptime Kuma:** create a **Push** monitor with a **180-second heartbeat interval**,
155-
**0 retries** and your notification channel. Copy its generated Push URL into:
156-
157-
```dotenv
158-
UPTIME_KUMA_PUSH_URL=https://kuma.example.com/api/push/REPLACE_WITH_PUSH_TOKEN
159-
```
185+
**0 retries** and your notification channel. In the config page's **Uptime Kuma** section,
186+
enter its generated secret Push URL, check **Enable Push monitoring**, and save. Changes
187+
apply within 30 seconds without a restart. The URL is never displayed again; leave it blank
188+
to keep the saved value. Uncheck monitoring and save to disable it.
160189

161190
The worker pushes at most every 60 seconds, plus status changes. It reports failure or
162191
overdue successful checks even while the container is running; if the worker disappears,
163192
Kuma detects the missing heartbeat. The URL is secret. No Docker socket or inbound worker
164193
port is required. See [the monitoring guide](docs/MONITORING.md) for startup behavior,
165194
freshness thresholds, private-network HTTP, notification tests, and all optional variables.
166-
Leave the URL empty to disable it completely.
195+
Legacy monitoring environment variables remain a fallback until settings are saved in the page.
167196

168197
## Documentation
169198

‎compose.yaml‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ services:
5757
options:
5858
max-size: "10m"
5959
max-file: "3"
60-
github-setup:
60+
github-config:
6161
platform: linux/amd64
6262
build:
6363
context: .
6464
platforms: [linux/amd64]
6565
entrypoint: ["gunicorn"]
6666
command: ["--bind", "0.0.0.0:8080", "--workers", "1", "--threads", "2",
6767
"--timeout", "120", "--graceful-timeout", "20",
68-
"--worker-tmp-dir", "/tmp", "github_backup.onboarding:application"]
68+
"--worker-tmp-dir", "/tmp", "github_backup.config_web:application"]
6969
restart: unless-stopped
7070
init: true
7171
read_only: true
@@ -80,8 +80,7 @@ services:
8080
- backup-cache:/cache
8181
expose: ["8080"]
8282
environment:
83-
GITHUB_SETUP_URL: ${GITHUB_SETUP_URL:-}
84-
GITHUB_SETUP_PASSWORD: ${GITHUB_SETUP_PASSWORD:-}
83+
GITHUB_CONFIG_URL: ${GITHUB_CONFIG_URL:-${GITHUB_SETUP_URL:-}}
8584
healthcheck:
8685
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health', timeout=5)"]
8786
interval: 60s

0 commit comments

Comments
 (0)