Skip to content

Commit 880a0e2

Browse files
authored
fix(template): finalize CA metadata and upstream env coverage (#38)
* fix(template): expose upstream self-hosting controls * fix(template): expose skylight controls with quiet defaults * fix(template): correct CA category and expose remaining upstream envs * chore(deps): refresh workflow and dockerfile pins
1 parent 0c54b5d commit 880a0e2

11 files changed

Lines changed: 171 additions & 27 deletions

File tree

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ jobs:
235235
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
236236

237237
- name: Build local test image
238-
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
238+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
239239
with:
240240
context: .
241241
platforms: linux/amd64
@@ -283,7 +283,7 @@ jobs:
283283
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
284284

285285
- name: Login to GHCR
286-
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
286+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
287287
with:
288288
registry: ${{ env.REGISTRY }}
289289
username: ${{ github.actor }}
@@ -312,7 +312,7 @@ jobs:
312312
313313
- name: Build and push
314314
id: build
315-
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
315+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
316316
with:
317317
context: .
318318
platforms: linux/amd64,linux/arm64
@@ -367,7 +367,7 @@ jobs:
367367
368368
- name: Create sync pull request
369369
if: ${{ env.SYNC_ENABLED == 'true' }}
370-
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
370+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
371371
with:
372372
token: ${{ secrets.SYNC_TOKEN }}
373373
path: target-repo

.github/workflows/check-upstream.yml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,41 @@ jobs:
3636
chmod +x scripts/check-upstream.py
3737
./scripts/check-upstream.py
3838
39-
- name: Stop if already current
40-
if: ${{ steps.upstream.outputs.updates_available != 'true' }}
41-
run: echo "Upstream is already current."
39+
- name: Stop if no stable version bump is available
40+
if: ${{ steps.upstream.outputs.version_update_available != 'true' }}
41+
run: |
42+
echo "No newer stable upstream Sure tag is available."
43+
if [[ "${{ steps.upstream.outputs.digest_update_available }}" == "true" ]]; then
44+
echo "Digest-only drift detected; leave that to Renovate or manual dependency refresh."
45+
fi
4246
4347
- name: Create update branch
44-
if: ${{ steps.upstream.outputs.updates_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
45-
run: git checkout -b "codex/upstream-${{ steps.upstream.outputs.latest_version }}"
48+
if: ${{ steps.upstream.outputs.version_update_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
49+
run: git checkout -B "codex/upstream-${{ steps.upstream.outputs.latest_version }}"
4650

4751
- name: Apply upstream version bump
48-
if: ${{ steps.upstream.outputs.updates_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
52+
if: ${{ steps.upstream.outputs.version_update_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
4953
env:
5054
WRITE_UPSTREAM_VERSION: "true"
5155
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5256
run: ./scripts/check-upstream.py
5357

5458
- name: Commit upstream version bump
55-
if: ${{ steps.upstream.outputs.updates_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
59+
if: ${{ steps.upstream.outputs.version_update_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
5660
run: |
5761
git config user.name "github-actions[bot]"
5862
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
5963
git add Dockerfile
60-
git commit -m "chore: bump upstream Sure to ${{ steps.upstream.outputs.latest_version }}"
64+
git commit -m "chore(sync): bump upstream sure to ${{ steps.upstream.outputs.latest_version }}"
6165
6266
- name: Push update branch
63-
if: ${{ steps.upstream.outputs.updates_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
67+
if: ${{ steps.upstream.outputs.version_update_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
6468
env:
6569
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6670
run: git push --force --set-upstream origin "codex/upstream-${{ steps.upstream.outputs.latest_version }}"
6771

6872
- name: Open or update pull request
69-
if: ${{ steps.upstream.outputs.updates_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
73+
if: ${{ steps.upstream.outputs.version_update_available == 'true' && steps.upstream.outputs.strategy == 'pr' }}
7074
env:
7175
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7276
run: |
@@ -86,12 +90,12 @@ jobs:
8690
existing_pr="$(gh pr list --head "codex/upstream-${{ steps.upstream.outputs.latest_version }}" --base main --json number --jq '.[0].number')"
8791
if [[ -n "${existing_pr}" ]]; then
8892
gh pr edit "${existing_pr}" \
89-
--title "chore: bump upstream Sure to ${{ steps.upstream.outputs.latest_version }}" \
93+
--title "chore(sync): bump upstream sure to ${{ steps.upstream.outputs.latest_version }}" \
9094
--body-file "${body_file}"
9195
else
9296
gh pr create \
9397
--base main \
9498
--head "codex/upstream-${{ steps.upstream.outputs.latest_version }}" \
95-
--title "chore: bump upstream Sure to ${{ steps.upstream.outputs.latest_version }}" \
99+
--title "chore(sync): bump upstream sure to ${{ steps.upstream.outputs.latest_version }}" \
96100
--body-file "${body_file}"
97101
fi

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
7070
- name: Create release PR
7171
if: steps.changes.outputs.has_changes == 'true'
72-
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
72+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
7373
with:
7474
commit-message: "chore(release): ${{ steps.version.outputs.release_version }}"
7575
title: "chore(release): ${{ steps.version.outputs.release_version }}"

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# syntax=docker/dockerfile:1@sha256:4a43a54dd1fedceb30ba47e76cfcf2b47304f4161c0caeac2db1c61804ea3c91
1+
# syntax=docker/dockerfile:1@sha256:2780b5c3bab67f1f76c781860de469442999ed1a0d7992a5efdf2cffc0e3d769
22

33
ARG UPSTREAM_VERSION=v0.6.9
4-
ARG UPSTREAM_IMAGE_DIGEST=sha256:3d899b3eced520d8d3166a3d53184cbb1356670fb52d050f94f8e62e59754d70
4+
ARG UPSTREAM_IMAGE_DIGEST=sha256:f415c4085489b4e154f2374786fd604b41ff11d3f56b6d1050fa28fa214f1130
55
ARG PGVECTOR_VERSION=0.8.2
66
FROM ghcr.io/we-promise/sure@${UPSTREAM_IMAGE_DIGEST}
77

@@ -53,6 +53,8 @@ RUN find /etc/s6-overlay/s6-rc.d -type f \( -name "run" -o -name "up" \) -exec c
5353
# 4. Expose the App Storage
5454
VOLUME ["/rails/storage", "/var/lib/postgresql/data", "/var/lib/redis"]
5555

56+
ENV SKYLIGHT_ENABLED=false
57+
5658
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
5759
CMD curl -f http://localhost:3000/up || exit 1
5860

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ If you just want to track your finances and don't care about databases, this is
3939

4040
While designed for absolute beginners, this container is intended to keep pace with upstream self-hosting features rather than stripping them out. The goal is straightforward: if upstream exposes a real self-hosting feature, the Unraid wrapper should either support it or document the gap plainly.
4141

42+
Some advanced Sure settings are intentionally managed as container environment variables in the Unraid template instead of only through Sure's web UI. When upstream sees one of those env vars, it may disable the matching control in the app and treat the template value as the source of truth. That is expected for this wrapper.
43+
This wrapper also defaults `SKYLIGHT_ENABLED=false` at the image level (and exposes it in the template) so AIO users are not required to configure upstream Skylight APM.
44+
4245
If you click **"Show more settings..."** in the Unraid template, you can customize the system deeply.
4346

4447
Read the comprehensive [Power User Guide here](docs/power-user.md) for instructions on how to configure:
@@ -63,6 +66,7 @@ Just make sure `/mnt/user/appdata/sure-aio` is covered by your standard Unraid C
6366

6467
- `Sure-AIO` now pins a specific upstream Sure version instead of following the floating `stable` tag.
6568
- The repo monitors stable upstream Sure tags and opens a PR when a newer stable version is released.
69+
- Upstream image digest drift is tracked separately so digest-only refreshes do not masquerade as version-bump PRs.
6670
- Every `main` package publish now ships the exact upstream version tag, an explicit AIO packaging line tag, `latest`, and `sha-<commit>`.
6771
- Formal wrapper releases follow the upstream version plus an AIO revision, such as `v0.6.8-aio.1`.
6872
- See the release workflow details in [docs/releases.md](docs/releases.md).

docs/power-user.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Track LLM inference costs and app usage.
6565
2. **PostHog:** Fill in your `POSTHOG_KEY` and `HOST` to track user analytics.
6666
3. **Langfuse:** Fill in your `LANGFUSE_HOST`, `PUBLIC_KEY`, and `SECRET_KEY` to chart token usage, latency, and costs of your AI operations.
6767
4. If you use hosted Langfuse and prefer a region shortcut instead of a full host URL, set `LANGFUSE_REGION` to `us` or `eu`. If `LANGFUSE_HOST` is set, it wins over the region shortcut.
68+
5. **Skylight APM:** `SKYLIGHT_ENABLED` defaults to `false` in this AIO wrapper (image default + template field) so users do not need any extra external service for normal operation. If you explicitly want Skylight, set `SKYLIGHT_ENABLED=true` and provide `SKYLIGHT_AUTHENTICATION` from your Skylight app settings.
6869

6970
---
7071

@@ -85,6 +86,8 @@ Sure relies on upstream providers for currency exchange rates and stock logos.
8586
* **Paid API Keys (Optional):** If you prefer Twelve Data, add your API key and change **[API] Exchange Rate Provider** and **[API] Securities Provider** to `twelve_data`.
8687
* **Logos:** Provide a **[API] Brandfetch Client ID** to automatically scrape high-res logos for your bank names and merchants.
8788
* **High-res logos:** Set `BRAND_FETCH_HIGH_RES_LOGOS=true` if you want Sure to prefer larger Brandfetch logo assets where available.
89+
* **Important override behavior:** If you set these provider and logo values in the Unraid template, upstream Sure treats them as env overrides and disables the matching controls in the self-hosting UI. In `sure-aio`, that is deliberate: the template is the power-user control plane.
90+
* **Advanced provider tuning:** The template also exposes `TWELVE_DATA_URL`, `YAHOO_FINANCE_URL`, `YAHOO_FINANCE_MAX_RETRIES`, `YAHOO_FINANCE_RETRY_INTERVAL`, and `YAHOO_FINANCE_MIN_REQUEST_INTERVAL` if you need proxying or retry tuning.
8891

8992
---
9093

@@ -100,8 +103,8 @@ To enable Single Sign-On (SSO):
100103
- `AUTH_JIT_MODE=link_only` if SSO should only link to existing users rather than auto-create them
101104
- `ALLOWED_OIDC_DOMAINS` to restrict which email domains may auto-create accounts through JIT SSO
102105
4. Optional button labels/icons are exposed too, along with dedicated Google and GitHub OAuth client fields if you want those providers separately.
103-
5. Upstream also supports additional named OIDC providers through env patterns like `OIDC_KEYCLOAK_*` or `OIDC_AUTHENTIK_*`. That is practical in raw compose files, but not cleanly representable in a static Unraid CA template. For this wrapper, the default generic OIDC path plus dedicated Google/GitHub options are exposed in the template; anything beyond that is a manual power-user customization.
104-
6. Upstream also uses `APP_URL` for some advanced SSO flows, especially SAML-style absolute callback and issuer generation. If you are doing advanced auth beyond the normal generic OIDC path, set `APP_URL` to your full external base URL such as `https://finance.example.com`.
106+
5. The template now also exposes `AUTH_PROVIDERS_SOURCE` plus named multi-provider envs like `OIDC_KEYCLOAK_*` and `OIDC_AUTHENTIK_*` if you want upstream's YAML-based or database-backed multi-provider SSO model.
107+
6. Upstream also uses `APP_URL` for advanced auth flows, especially absolute callback and issuer generation. If you are doing advanced auth beyond the normal generic OIDC path, set `APP_URL` to your full external base URL such as `https://finance.example.com`.
105108

106109
### SMTP Mail Relay (For Password Resets / Reports)
107110
1. Find the **[Email]** block.
@@ -179,6 +182,45 @@ For most Unraid installs, plain container logs are enough. If you want centraliz
179182

180183
---
181184

185+
## 12. Sync, Plaid, and Runtime Tuning
186+
187+
The template now exposes the main upstream runtime toggles that were previously only obvious in docs or code:
188+
189+
1. **Sync scheduling**
190+
- `AUTO_SYNC_ENABLED`
191+
- `AUTO_SYNC_TIME`
192+
- `AUTO_SYNC_TIMEZONE`
193+
2. **Pending transaction behavior**
194+
- `SIMPLEFIN_INCLUDE_PENDING`
195+
- `PLAID_INCLUDE_PENDING`
196+
- Just like provider selection, these env overrides lock the matching Sync control in Sure's UI when set.
197+
3. **Plaid credentials**
198+
- `PLAID_CLIENT_ID`
199+
- `PLAID_SECRET`
200+
- `PLAID_ENV`
201+
- `PLAID_EU_CLIENT_ID`
202+
- `PLAID_EU_SECRET`
203+
- `PLAID_EU_ENV`
204+
4. **OpenAI compatibility tuning**
205+
- `OPENAI_REQUEST_TIMEOUT`
206+
- `LLM_JSON_MODE`
207+
- `CATEGORIZATION_PROVIDER` / `CATEGORIZATION_MODEL`
208+
- `CHAT_PROVIDER` / `CHAT_MODEL`
209+
5. **Auth and onboarding behavior**
210+
- `REQUIRE_EMAIL_CONFIRMATION`
211+
- `AUTH_PROVIDERS_SOURCE`
212+
6. **Database and SSL edge cases**
213+
- `POSTGRES_DB`
214+
- `SSL_CERT_FILE`
215+
7. **Advanced outbound networking**
216+
- `HTTPS_PROXY`
217+
- `HTTP_PROXY`
218+
- `NO_PROXY`
219+
220+
These are all legitimate upstream runtime knobs, but not all of them belong in a beginner walkthrough. They are here because `sure-aio` should expose the real self-hosting surface without forcing users to rebuild the image just to reach it.
221+
222+
---
223+
182224
## Trial / Subscription Note
183225

184226
Upstream `v0.6.9` is supposed to disable subscription and trial gating in self-hosted mode when `SELF_HOSTED=true`. The 45-day trial logic still exists in the codebase, but upstream guards it behind `app_mode != self_hosted`.

docs/releases.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
`sure-aio` uses upstream-version-plus-AIO-revision releases such as `v0.6.8-aio.1`.
44

5+
Stable upstream version monitoring and upstream image digest monitoring are separate concerns. Version bumps should open explicit upstream-update PRs, while digest-only refreshes should flow through normal dependency update automation.
6+
57
## Version format
68

79
- first wrapper release for upstream `v0.6.8`: `v0.6.8-aio.1`

rootfs/root/.skylight

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
disable_env_warning: true

scripts/check-upstream.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,11 @@ def main() -> None:
251251
current_digest = read_local_digest(upstream)
252252
latest_version = latest_github_tag(str(upstream.get("repo", "")).strip(), stable_only)
253253
latest_digest = latest_ghcr_digest(str(upstream.get("image", "")).strip(), "latest")
254-
updates_available = latest_version != current_version or latest_digest != current_digest
254+
version_update_available = latest_version != current_version
255+
digest_update_available = latest_digest != current_digest
256+
updates_available = version_update_available
255257

256-
if os.environ.get("WRITE_UPSTREAM_VERSION") == "true" and updates_available:
258+
if os.environ.get("WRITE_UPSTREAM_VERSION") == "true" and version_update_available:
257259
write_local_version(upstream, latest_version)
258260
write_local_digest(upstream, latest_digest)
259261

@@ -270,6 +272,8 @@ def main() -> None:
270272
"current_digest": current_digest,
271273
"latest_digest": latest_digest,
272274
"updates_available": "true" if updates_available else "false",
275+
"version_update_available": "true" if version_update_available else "false",
276+
"digest_update_available": "true" if digest_update_available else "false",
273277
"strategy": str(upstream.get("strategy", "pr")).strip() or "pr",
274278
"upstream_name": str(upstream.get("name", "")).strip(),
275279
"release_notes_url": release_notes,

scripts/validate-template.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,18 @@
2424
"AUTH_JIT_MODE",
2525
"AUTH_LOCAL_ADMIN_OVERRIDE_ENABLED",
2626
"AUTH_LOCAL_LOGIN_ENABLED",
27+
"AUTH_PROVIDERS_SOURCE",
28+
"AUTO_SYNC_ENABLED",
29+
"AUTO_SYNC_TIME",
30+
"AUTO_SYNC_TIMEZONE",
2731
"ALLOWED_OIDC_DOMAINS",
2832
"BRAND_FETCH_CLIENT_ID",
2933
"BRAND_FETCH_HIGH_RES_LOGOS",
3034
"BRAND_NAME",
35+
"CATEGORIZATION_MODEL",
36+
"CATEGORIZATION_PROVIDER",
37+
"CHAT_MODEL",
38+
"CHAT_PROVIDER",
3139
"CLOUDFLARE_ACCESS_KEY_ID",
3240
"CLOUDFLARE_ACCOUNT_ID",
3341
"CLOUDFLARE_BUCKET",
@@ -66,21 +74,42 @@
6674
"LANGFUSE_SECRET_KEY",
6775
"LEGAL_PRIVACY_URL",
6876
"LEGAL_TERMS_URL",
77+
"LLM_JSON_MODE",
6978
"LOGTAIL_API_KEY",
7079
"LOGTAIL_INGESTING_HOST",
80+
"HTTP_PROXY",
81+
"HTTPS_PROXY",
7182
"MCP_API_TOKEN",
7283
"MCP_USER_EMAIL",
84+
"NO_PROXY",
7385
"OIDC_BUTTON_ICON",
7486
"OIDC_BUTTON_LABEL",
87+
"OIDC_AUTHENTIK_CLIENT_ID",
88+
"OIDC_AUTHENTIK_CLIENT_SECRET",
89+
"OIDC_AUTHENTIK_ISSUER",
90+
"OIDC_AUTHENTIK_REDIRECT_URI",
7591
"OIDC_CLIENT_ID",
7692
"OIDC_CLIENT_SECRET",
7793
"OIDC_ISSUER",
94+
"OIDC_KEYCLOAK_CLIENT_ID",
95+
"OIDC_KEYCLOAK_CLIENT_SECRET",
96+
"OIDC_KEYCLOAK_ISSUER",
97+
"OIDC_KEYCLOAK_REDIRECT_URI",
7898
"OIDC_REDIRECT_URI",
7999
"ONBOARDING_STATE",
80100
"OPENAI_ACCESS_TOKEN",
81101
"OPENAI_MODEL",
102+
"OPENAI_REQUEST_TIMEOUT",
82103
"OPENAI_SUPPORTS_PDF_PROCESSING",
83104
"OPENAI_URI_BASE",
105+
"PLAID_CLIENT_ID",
106+
"PLAID_ENV",
107+
"PLAID_EU_CLIENT_ID",
108+
"PLAID_EU_ENV",
109+
"PLAID_EU_SECRET",
110+
"PLAID_INCLUDE_PENDING",
111+
"PLAID_SECRET",
112+
"POSTGRES_DB",
84113
"POSTGRES_PASSWORD",
85114
"POSTGRES_USER",
86115
"POSTHOG_HOST",
@@ -96,22 +125,33 @@
96125
"REDIS_SENTINEL_MASTER",
97126
"REDIS_SENTINEL_USERNAME",
98127
"REDIS_URL",
128+
"REQUIRE_EMAIL_CONFIRMATION",
99129
"S3_ACCESS_KEY_ID",
100130
"S3_BUCKET",
101131
"S3_REGION",
102132
"S3_SECRET_ACCESS_KEY",
103133
"SECRET_KEY_BASE",
104134
"SECURITIES_PROVIDER",
135+
"SENTRY_DSN",
136+
"SKYLIGHT_AUTHENTICATION",
137+
"SKYLIGHT_ENABLED",
105138
"SMTP_ADDRESS",
106139
"SMTP_PASSWORD",
107140
"SMTP_PORT",
108141
"SMTP_TLS_ENABLED",
109142
"SMTP_USERNAME",
143+
"SIMPLEFIN_INCLUDE_PENDING",
110144
"SSL_CA_FILE",
145+
"SSL_CERT_FILE",
111146
"SSL_DEBUG",
112147
"SSL_VERIFY",
113148
"TWELVE_DATA_API_KEY",
149+
"TWELVE_DATA_URL",
114150
"VECTOR_STORE_PROVIDER",
151+
"YAHOO_FINANCE_MAX_RETRIES",
152+
"YAHOO_FINANCE_MIN_REQUEST_INTERVAL",
153+
"YAHOO_FINANCE_RETRY_INTERVAL",
154+
"YAHOO_FINANCE_URL",
115155
}
116156

117157

0 commit comments

Comments
 (0)