Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Offical apps | Community apps | Demo | Docs | Install
S

shrey

@shrey
Unfollow Follow
About
Posts
328
Topics
78
Shares
0
Groups
0
Followers
1
Following
0

Posts

Recent Best Controversial

  • Broken Update n8n to 2.36.8
    S shrey
    N8N

    @DualOSWinWiz
    Facing the same issue.

    Unable to provide corresponding logs atm. Had to do a quick rollback to the last version.


  • REST API broken since last update
    S shrey
    Cubby

    @james said:

    So what you need is a way for users in Cubby to create auth tokens that can be used with the API, right?

    Yes, essentially.


  • REST API broken since last update
    S shrey
    Cubby

    @nebulon said:

    Please do not dump AI output directly into the forum.

    Fair enough.


    My use-case: Headless, auth enabled filestore with link-based sharing mechanism, with a decent admin GUI. Cubby seems to fulfil most of this, except for the 'headless automation as a first-class feature' aspect. Basically, upload files/folders, and generate unique, revocable and individual share links for them, as required. Currently, i'm managing those links in another online spreadsheet tool.

    Btw, i got around to Cubby after i searched for a solution in the Cloudron App Store, and couldn't identify any useful-enough option.

    OIDC is going to be tricky due to the interactive nature of the auth mechanism, assuming that the access token issued there are short-lived.

    So yeah, an ideal solution would be a long-lived access token/API key that allows for full programmatic access to the REST API


  • REST API broken since last update
    S shrey
    Cubby

    @nebulon
    Compiled with assistance from Claude:


    You're right that the auth code path is unchanged. Nothing about how Cubby resolves a credential changed. What changed is how long a token survives, and that's enough to break Bearer-authenticated API use.

    Answering your questions directly first.

    What I was actually doing, since that seems unexpected

    I've been driving Cubby's REST API server-to-server since late June, as a headless file store for an automation pipeline. A dedicated service user owns one folder; that folder has a single read-only share, so published files are readable over a public link while writes stay authenticated. There is no browser and no user session anywhere in this — just an HTTP client sending Authorization: Bearer <token>, where the token is a row in the tokens table, resolved by getUserFromToken → users.getByAccessToken → tokens.get. Not the OpenID access token.

    Endpoints in use, all with that same Bearer credential:

    Purpose Call
    Write / overwrite a file POST /api/v1/files?path=/home/<folder>/<name>&overwrite=true, raw binary body with the real Content-Type
    Create a folder POST /api/v1/files?path=<path>&directory=true
    Read, list, delete, rename GET / DELETE / relocate on /api/v1/files
    Publish a per-file link POST /api/v1/shares with { path, readonly: true, ownerUsername: <service user> }
    Revoke a link DELETE /api/v1/shares?shareId=<id>
    Public read of a published file GET /api/v1/shares/<shareId>?type=raw — no auth, and this still works fine

    That last row is why the app kept looking healthy: reads go through the share and never touch the token. Only the authenticated write path broke.

    The failing request, from my client's execution log, 2026-08-08T08:41:15Z:

    POST https://<my-cubby>/api/v1/files?path=/home/<folder>/<file>.svg&overwrite=true
    Content-Type: image/svg+xml
    Content-Length: 199
    Authorization: Bearer <redacted>
    
    → 403 {"status": "Forbidden", "message": "not allowed"}
    

    Do I see errors in backend or frontend

    No. There is no frontend involved — this is server-to-server. And the backend logs nothing, because a request bearing a deleted token isn't treated as an error at all; it's treated as an anonymous request and rejected in path resolution. debugLog is off without DEBUG set, so nothing is written.

    I ran the same request with no credential at all and got a byte-identical 403. So an expired credential and an absent credential are indistinguishable to the client and invisible on the server. That's what made this hard to diagnose: my first assumption was a permissions or share-ownership problem, and my initial post here blamed the wrong credential type as a result.

    What changed

    Commit 00c42b6681d57b1a6428ad4e458fa2c1285bc937 — "Add wopi lock support for collaboration", 2026-07-21T07:14:42Z.
    https://github.com/getcubby/cubby/commit/00c42b6681d57b1a6428ad4e458fa2c1285bc937

    Alongside the WOPI lock work, it added to backend/tokens.js:

    async function cleanup(maxAgeMs) {
        const cutoff = new Date(Date.now() - maxAgeMs);
        await database.query('DELETE FROM tokens WHERE created_at < $1', [ cutoff ]);
    }
    

    and wired it up in backend/server.js:

    const TOKEN_MAX_AGE_MS = 24 * 60 * 60 * 1000;
    ...
    tokens.cleanup(TOKEN_MAX_AGE_MS)                    // at boot
    gTokenCleanupInterval = setInterval(() => {
        tokens.cleanup(TOKEN_MAX_AGE_MS)
    }, 60 * 60 * 1000);                                 // then hourly
    

    cleanup() did not exist before this commit. backend/tokens.js has nine commits in its entire history; the one before this is "Port to esm" from 2026-02-25, which was mechanical.

    I understand why it's there — getHandle calls tokens.add() on every open and every collaborator join, so an office session accumulates rows quickly and something has to reap them. That's reasonable. The issue is that tokens is one undifferentiated table, and add() writes only (id, username) — there's no column recording what a token is for, so cleanup() can only sweep everything. WOPI handles and API tokens are the same row shape, so both go.

    Which release it shipped in

    When (UTC) What
    2026-07-02 08:39 package version → 2.15.1
    2026-07-21 07:14 00c42b6 — reaper added
    2026-07-21 16:17 dc23534 — further WOPI work (touches tokens.js, but does not alter cleanup)
    2026-07-21 16:38 Renovate bumps app digest to 56b1426
    2026-07-21 17:27 package version → 2.16.0

    So the reaper is in 2.16.0 and in no earlier release.

    Where my token came from, since it's relevant. I minted it on 28 June by inserting the row directly, inside the container via cloudron exec, with a small script that did crypto.randomBytes(32).toString('hex') and then INSERT INTO tokens (id, username) VALUES ($1, $2). That is the same statement tokens.add() runs, so the row is indistinguishable from one issued through the mobile flow — but I should be straight that I put it there myself rather than obtaining it through a supported path. I went that way because at the time the source had no token TTL anywhere in it, and there was no other non-interactive way to get a credential.

    I'm reporting it because two things behind it aren't specific to me at all: the 403 that should be a 401, and a reaper that can't tell one kind of token from another.

    20 days, 12 hours of continuous validity on a single token, with timestamps on both ends. Whatever the intended lifetime is now, nothing was expiring tokens before 2.16.0.

    My client's execution history brackets it the same way. Successful writes on:

    • 1 July — 5 executions
    • 7 July — 7 executions
    • 18 July — 5 executions, last at 2026-07-18T18:08:59Z

    Then the pipeline sat idle. The next write attempt was 2026-08-08T08:41:15Z — 21 days later, across the 2.16.0 boundary — and it 403'd, as did every attempt after it until I moved to WebDAV on 9 August. There are no executions in the gap, so this isn't a case of it degrading unnoticed; the first use after the update simply failed.

    Why the response is 403 and not 401

    backend/routes/files.js, add():

    const subject = await files.translateResourcePath(req.user?.username, filePath);
    if (!subject) return next(new HttpError(403, 'not allowed'));          // line 33-34
    
    if (subject.share?.readonly) return next(new HttpError(403, 'share is read-only'));
    if (!subject.share && !req.user) return next(new HttpError(401, 'not allowed')); // line 37
    

    and backend/files.js:

    // only shares may have optional auth
    if (resource !== 'shares' && !username) return null;
    

    For a /home/... path with no resolved user, translateResourcePath returns null, so line 34 fires and the 401 on line 37 is unreachable. The 401 you already wrote for exactly this case can never be reached on /home paths — it only applies to share paths.

    Swapping those two checks (or returning 401 when !username && resource !== 'shares') would turn this class of failure from silent into immediately diagnosable, independently of anything about token lifetime.

    One thing worth checking on your side

    The cutoff is measured from mint, not from last use — tokens.get is a plain SELECT and never touches created_at, so there's no sliding window. A token dies 24 hours after it was issued no matter how actively it's being used.

    That applies to mobile tokens too. POST /api/v1/mobile/code-to-token returns:

    next(new HttpSuccess(200, {
        token: apiToken,
        user: { username, email, displayName, admin }
    }));
    

    — no expiry field, no refresh token, and no refresh path on that endpoint. So server-side, a token issued to org.getcubby.app stops resolving within 24 hours of issue, where before 2.16.0 it didn't expire at all.

    I can't see the Android app's source, so I don't know what it does when its token stops working — if it silently re-runs the pairing flow against a live IdP session, users may never notice. Flagging it in case that path isn't as silent as it needs to be now.

    What I'd ask for

    1. Record a token type at mint time and have cleanup() filter on it, so the WOPI sweep only reaps WOPI tokens. If a blanket 24-hour lifetime on all tokens is intended, that's fine — but it needs a changelog line and a doc note. The 2.16.0 entry lists the activity log, file drop, office collaboration, recents fixes and dependencies; nothing about tokens.
    2. Return 401 when a credential is presented and doesn't resolve. Three-line change, and it's correct HTTP regardless of the rest. WebDAV already gets this right — webdav.js sends WWW-Authenticate: Basic realm="Cubby" on an unauthenticated request.
    3. A supported way to obtain a durable API credential. Right now tokens.add() is reachable only from the mobile OIDC exchange and the WOPI flow; the browser UI has used cookie sessions since 0.7.0. So there's no non-interactive way to get a token, and POST /api/v1/shares is isAuthenticated, meaning share creation has no non-interactive path at all. verifyCloudronCredentials already exists in webdav.js and works — accepting App Passwords via Basic auth on /api/v1/* too would solve this cleanly, if that's less work than it looks from outside.

    I've moved my file operations to WebDAV with a Cloudron App Password, which is durable and has no token involved, so I'm not blocked. Reporting it because the silent-403 behaviour will catch others the same way, and because of the mobile app question above.

    Reproducing

    Reaper history, no instance needed:

    git clone --filter=blob:none https://github.com/getcubby/cubby.git && cd cubby
    git log -S "TOKEN_MAX_AGE_MS" --date=iso --pretty="%ad %H %s"
    git log --follow --date=iso --pretty="%ad %h %s" -- backend/tokens.js
    

    Silent 403, any instance — no credential at all:

    curl -s -w '\n%{http_code}\n' -X POST \
      'https://<cubby>/api/v1/files?path=/home/x&directory=true'
    

  • REST API broken since last update
    S shrey
    Cubby

    I had been using Cubby via its REST API, without any issues until July 18th, before the last update.
    But now, i'm getting Auth errors everytime.
    As far as i can remember, i had used an App Password (scoped to Cubby) earlier.


  • XBackBone package: uploads > 1 GiB rejected with 413
    S shrey
    XBackBone

    @james Just installed the updated package and tried it out.
    Seems to be working without issues, so far.
    Thanks!


  • XBackBone package: uploads > 1 GiB rejected with 413
    S shrey
    XBackBone

    Summary:

    On the XBackBone package, uploads larger than 1 GiB fail with HTTP 413. The package's Apache vhost (apache/xbackbone.conf) defines no LimitRequestBody, so Apache 2.4.58 applies its built-in 1 GiB default. Apache rejects the request before PHP is reached, so raising post_max_size/upload_max_filesize via /app/data/php.ini has no effect. The app's advertised limit (25 GB, derived from PHP) is therefore misleading.

    Environment:

    App: XBackBone (v3.8.2), base image cloudron/base:5.0.0
    apache2 -v → Apache/2.4.58 (Ubuntu), built 2024-10-02
    Modules: mpm_prefork_module, php_module (mod_php, PHP 8.3)
    Standard Cloudron reverse proxy; no external proxy in front

    Observed on my instance (Web Terminal):
    LimitRequestBody is unset anywhere in Apache config or app code:

    grep -rniE 'LimitRequestBody' /etc/apache2/ /app/code/  → no matches
    

    PHP is not the limiter:

    php -r '... ini_get ...'
    post_max_size=25G
    upload_max_filesize=25G
    memory_limit=-1
    

    Calling the container's Apache directly (localhost:80, bypassing the Cloudron proxy), bracketing 1 GiB:

    curl -F upload=@900M   http://localhost:80/upload/web  → HTTP 302
    curl -F upload=@1100M  http://localhost:80/upload/web  → HTTP 413
    
    #response headers on the 1100M request:
    HTTP/1.1 413 Request Entity Too Large
    Server: Apache/2.4.58 (Ubuntu)
    

    This confirms the 413 originates from the app container's Apache (not the Cloudron proxy), and the threshold is the 1 GiB Apache default. In the browser, the same upload surfaces as Server: nginx because the platform proxy relabels the response header.

    Root cause:

    Apache 2.4.54+ ships a default LimitRequestBody of 1 GiB (1073741824 bytes) instead of unlimited (CVE-2022-29404). Because apache/xbackbone.conf sets no explicit value, every upload is capped at 1 GiB regardless of PHP configuration or the app's stated maximum.

    Impact:

    The effective upload ceiling (1 GiB) contradicts both the UI's advertised limit and the documented php.ini tuning path.

    The fix is not available to users: the vhost lives at /etc/apache2/sites-enabled/xbackbone.conf on the read-only container filesystem, LimitRequestBody cannot be expressed via php.ini or /app/data, and XBackBone's .htaccess sits in read-only /app/code. A package change is required.

    Proposed fix:

    Add an explicit LimitRequestBody to apache/xbackbone.conf, deferring the ceiling to PHP's post_max_size (the value users are already directed to set):

    # Apache 2.4.54+ defaults `LimitRequestBody` to 1 GiB (CVE-2022-29404).
    # Defer the upload ceiling to PHP `post_max_size` (set via /app/data/php.ini).
    LimitRequestBody 0
    

    Alternatively, derive LimitRequestBody from the effective post_max_size in start.sh so the two stay in sync. The docs at docs.cloudron.io/apps/xbackbone should also be updated, as they currently present php.ini as the sole upload-size control.

    Verification for the fix:

    After patching, upload a file > 1 GiB (e.g. dd if=/dev/zero of=test bs=1M count=1200). Currently returns 413; should succeed.

    Reference:

    Package file to patch: https://git.cloudron.io/packages/xbackbone-app/-/blob/master/apache/xbackbone.conf
    Apache LimitRequestBody: https://httpd.apache.org/docs/2.4/mod/core.html#limitrequestbody


    PS: Troubleshooting conducted & this summary prepared in collaboration with Claude


  • Plan for Directus updates?
    S shrey
    Directus

    Hi @cloudron team, could you kindly share the plan for upcoming Directus packages, given that the Directus has moved to v12 (with a whole bunch of breaking changes, including significant changes to the license and online/offline capability?

    https://github.com/directus/directus/releases

    https://directus.com/resources/v12-built-for-the-whole-team

    https://directus.com/oig


  • v3.24.0 constantly runs out of memory
    S shrey
    Umami

    Yeah, same here. Had to roll back to the last version.


  • how do I stop a app
    S shrey
    Support userinterface

    Same here. Found the move rather odd.


  • Backup Region (DigitalOcean Spaces) not available
    S shrey
    Support digitalocean backups

    It seems that the Backup options don't provide a full list of regions for the DigitalOcean Spaces.

    See: https://docs.digitalocean.com/products/spaces/details/availability/

    Cloudron options:
    99987fdc-3e1d-470e-bfc3-ffd1bdf3bc59-image.png

    PS: Currently, i have been able to work around this by using the "S3 API (v4)" option instead, but it would be nice if the native dialog for DO Spaces included the entire list of available regions.


  • Grist | The Evolution of Spreadsheets
    S shrey
    App Wishlist

    Hi @timconsidine, i would certainly like to try out your Grist package.

    After initially not finding Grist on Cloudron, i ended up deploying it on another VPS, using a Portainer/docker-compose based setup.

    Would be great if the complete Grist package can be managed within Cloudron itself!


  • Stirling v2: How to change password
    S shrey
    Stirling-PDF

    Just came here for the same issue.
    Can't see any way to change the admin default password!


  • Error: Domain nameservers are not set to NameCheap
    S shrey
    Support dns namecheap

    @james said in Error: Domain nameservers are not set to NameCheap:

    This could be a bug. Can you try to cancel the change location task and create it again?

    Done!
    Sorry, my first time with this sort of Subdomain delegations.

    In the Retry Task, I had to change the location to the newly added, 'subdomain as root' option.

    Thanks again!


  • Error: Domain nameservers are not set to NameCheap
    S shrey
    Support dns namecheap

    @james said in Error: Domain nameservers are not set to NameCheap:

    This could be a bug. Can you try to cancel the change location task and create it again?

    I tried that. But this is the only option available:
    477addee-8386-436b-af4e-e92d259f8a84-image.png

    And every time i try the "Retry task", it falls back into the same loop.


  • Error: Domain nameservers are not set to NameCheap
    S shrey
    Support dns namecheap

    @james @girish Thanks for the quick replies!

    It seems that i had missed setting the proper value for the "Zone Name", which is necessary in my case as the Domain and the concerned Subdomain are hosted in 2 different places..

    I have now added the value and Synced DNS. But, i'm still facing issue in bringing up the app. It seems the Retry Location change tasks is still checking against the earlier Nameservers, and not the latest ones.

    Nov 24 14:59:10 box:dns/waitfordns waitForDns: nameservers are ["ns02.one.com","ns01.one.com"]
    Nov 24 14:59:11 box:dns/waitfordns resolveIp: Checking A for <subdomain> at 185.10.11.10
    Nov 24 14:59:11 box:dns/waitfordns resolveIp: No A. Checking CNAME for <subdomain> at 185.10.11.10
    Nov 24 14:59:11 box:dns/waitfordns isChangeSynced: NS ns02.one.com (185.10.11.10) errored when resolve <subdomain> (A): Error: queryCname ENODATA <subdomain>
    Nov 24 14:59:11 box:dns/waitfordns resolveIp: Checking A for <subdomain> at 2001:67c:3c0::10
    Nov 24 14:59:11 box:dns/waitfordns resolveIp: No A. Checking CNAME for <subdomain> at 2001:67c:3c0::10
    Nov 24 14:59:11 box:dns/waitfordns isChangeSynced: NS ns02.one.com (2001:67c:3c0::10) errored when resolve <subdomain> (A): Error: queryCname ENODATA <subdomain>
    Nov 24 14:59:11 box:dns/waitfordns Attempt 10 failed. Will retry: ETRYAGAIN
    

  • Error: Domain nameservers are not set to NameCheap
    S shrey
    Support dns namecheap

    (Sub-)Domain setup error:

    Domain nameservers are not set to NameCheap
    

    Where can i check which values are being compared with, by Cloudron, for the nameservers belonging to NameCheap?

    My initial suspicion is that only the default Nameservers of NameCheap might be used for checking, and not the additional options like FreeDNS (which i'm using) [See: NameCheap FreeDNS]


  • MiroTalk SFU: Recording not possible?
    S shrey
    MiroTalk

    Additionally, it seems like if:
    Start recording > [time elapses] > Stop recording > Start Recording again > [time elapses] > Stop Recording/Exit Meeting
    Only the last recording gets saved (overwriting the first part).


  • MiroTalk SFU: Recording not possible?
    S shrey
    MiroTalk

    @james
    Current behaviour:

    1. I start a meeting as Host
    2. Start the Recording (only Host is allowed to record)
    3. Once meeting is over, i stop the meeting by clicking on "Leave Room"
    4. The recording is available in /app/data/rec but not in S3.

    If, in Step 3:
    i stop the Recording and then stop the meeting, only then the Recording gets uploaded to S3.

    Expectation:
    Recording should get uploaded to S3 regardless of the path taken to 'stop' the meeting and without explicitly stopping the recording.


  • MiroTalk SFU: Recording not possible?
    S shrey
    MiroTalk

    @james said in MiroTalk SFU: Recording not possible?:

    Change AWS_S3_BUCKET_NAME to AWS_S3_BUCKET restart and it should be working.

    Thanks!
    That did get it working.


    @mirotalk-57bab571 Just one more kink remaining:

    When i 'disconnect' the call without stopping the recording, the Recording seems to get saved only in the local directory, and not S3. The S3 upload seems to be triggered only when an ongoing recording is stopped explicitly.

  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search