{"id":51623749,"url":"https://github.com/abnvle/oxicloud-public-proxy","last_synced_at":"2026-07-12T22:01:33.166Z","repository":{"id":356132737,"uuid":"1230147768","full_name":"abnvle/oxicloud-public-proxy","owner":"abnvle","description":"Reverse proxy that publishes OxiCloud share links on a public domain while keeping OxiCloud itself private.","archived":false,"fork":false,"pushed_at":"2026-05-29T22:45:44.000Z","size":1701,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T00:14:32.135Z","etag":null,"topics":["cloud","dropbox","file-share","file-sync","file-upload","filesharing","nas","nextcloud","nextcloud-alternative","onedrive","open-source","own-your-data","owncloud","oxicloud","proxy","s3-storage","security","self-hosted","webdav"],"latest_commit_sha":null,"homepage":"https://evtlab.pl","language":"EJS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abnvle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-05T18:14:16.000Z","updated_at":"2026-05-29T22:37:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abnvle/oxicloud-public-proxy","commit_stats":null,"previous_names":["abnvle/oxicloud-public-proxy"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/abnvle/oxicloud-public-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abnvle%2Foxicloud-public-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abnvle%2Foxicloud-public-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abnvle%2Foxicloud-public-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abnvle%2Foxicloud-public-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abnvle","download_url":"https://codeload.github.com/abnvle/oxicloud-public-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abnvle%2Foxicloud-public-proxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35403795,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloud","dropbox","file-share","file-sync","file-upload","filesharing","nas","nextcloud","nextcloud-alternative","onedrive","open-source","own-your-data","owncloud","oxicloud","proxy","s3-storage","security","self-hosted","webdav"],"created_at":"2026-07-12T22:01:32.596Z","updated_at":"2026-07-12T22:01:33.157Z","avatar_url":"https://github.com/abnvle.png","language":"EJS","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/logo.png\" alt=\"OxiCloud\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eoxicloud-public-proxy\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Public reverse proxy for \u003ca href=\"https://github.com/AtalayaLabs/OxiCloud\"\u003eOxiCloud\u003c/a\u003e share links.\n\u003c/p\u003e\n\n---\n\n## Compatibility\n\nRequires OxiCloud **0.6.0 \"Open Skies\"** or newer. Both upstream patches the proxy depends on ([#346](https://github.com/AtalayaLabs/OxiCloud/pull/346), [#347](https://github.com/AtalayaLabs/OxiCloud/pull/347)) are included in that release, so all features - file shares, password-protected shares, folder browsing and ZIP downloads - work out of the box.\n\nOlder OxiCloud versions are not supported.\n\n---\n\n## Overview\n\nA small Node.js service that sits between the public internet and a private\nOxiCloud instance. The only thing it exposes is the share-link URLs\n(`/share/\u003ctoken\u003e`); your file browser, admin panel, and authentication stay\nunreachable from outside.\n\nWhen someone opens a share link on your public hostname, the proxy:\n\n1. Calls OxiCloud's public share API on the private network.\n2. Renders the result with a templated HTML view (file metadata, password\n   prompt, folder gallery, expired notice).\n3. Streams file downloads through, forwarding `Range`, `ETag` and\n   `Set-Cookie` headers so video seek, resumable downloads, and password\n   sessions work the same as on the upstream.\n\nThe proxy holds no OxiCloud credentials. Authorization is the share token\nonly, the same as opening a share directly on an exposed OxiCloud.\n\n## Demo\n\nA live instance is running at [oxi-demo.evtlab.pl](https://oxi-demo.evtlab.pl).\n\n- Example share: \u003chttps://oxi-demo.evtlab.pl/share/6bb56212-e582-4fa5-989d-742562ad7520\u003e\n- Password: `demo123`\n\n\u003e **Note:** The demo runs against OxiCloud 0.6.0, so all features are available.\n\n## Features\n\n- File shares, with or without a password\n- Folder shares with full in-browser browsing\n  - Grid or list view, persisted per-browser\n  - Image thumbnails, lazy-loaded video posters\n  - Click-to-open lightbox with keyboard navigation\n  - File-type icons (PDF, archive, code, fonts, ...)\n  - Subfolder navigation with browser back support\n- ZIP download for any folder in the share, root or subfolder\n- `Range` / `ETag` passed through, so video seek and resumable downloads work\n- English and Polish UI, picked from `Accept-Language`, override with `?lang=`\n- A small landing page at `/` if someone hits the root\n\n## Requirements\n\n- Docker (for the recommended deployment)\n- A reverse proxy in front for TLS (nginx, Traefik, Nginx Proxy Manager,\n  Caddy, ...)\n- An OxiCloud instance reachable from the proxy. A Docker service name, a\n  LAN address, or a VPN address all work, as long as the proxy can call it\n\nFor local development without Docker: Node 22+ and `npm`.\n\n## Quick start\n\n```bash\ngit clone https://github.com/abnvle/oxicloud-public-proxy.git\ncd oxicloud-public-proxy\ncp .env.example .env\n# edit .env, set OXICLOUD_INTERNAL_URL and PUBLIC_BASE_URL\ndocker compose up -d --build\n```\n\nPoint your reverse proxy at `localhost:3000` and route your public hostname\nthere. The proxy itself does not terminate TLS.\n\n## Configuration\n\n| Variable | Default | Required | Notes |\n|---|---|---|---|\n| `OXICLOUD_INTERNAL_URL` | | yes | URL of OxiCloud reachable from the proxy. A Docker service name like `http://oxicloud:8086` or a LAN address like `http://192.168.0.205:8086`. |\n| `PUBLIC_BASE_URL` | | yes | The public URL the proxy is served from, e.g. `https://files.example.com`. |\n| `PORT` | `3000` | no | TCP port. Used for both the host port mapping in `docker-compose.yml` and the in-container listener, so they stay in sync. |\n| `HOST` | `0.0.0.0` | no | Bind address. Default is right for containers. |\n| `LOG_LEVEL` | `info` | no | One of `fatal`, `error`, `warn`, `info`, `debug`, `trace`. |\n\nSee `.env.example` for a copy-and-edit starting point.\n\n### OxiCloud side\n\nSet `OXICLOUD_BASE_URL` on your OxiCloud instance to the proxy's public URL,\nso share links generated in the OxiCloud UI point at the proxy:\n\n```\nOXICLOUD_BASE_URL=https://files.example.com\n```\n\nOxiCloud generates `/s/\u003ctoken\u003e` URLs; the proxy serves the canonical\n`/share/\u003ctoken\u003e` path and redirects `/s/\u003ctoken\u003e` to it, so links copied\nfrom OxiCloud work as-is.\n\n## Routes\n\n```\nGET  /                              landing page\nGET  /healthcheck                   liveness probe (200 / \"ok\")\nGET  /s/:token                      301 → /share/:token (OxiCloud-native URL format)\nGET  /share/:token                  share page (file / folder / password / expired)\nPOST /share/:token/auth             submit password\nGET  /share/:token/download         file share download\nGET  /share/:token/folder/:id       subfolder gallery\nGET  /share/:token/file/:id         file inside folder share\nGET  /share/:token/zip              folder share as ZIP\nGET  /share/:token/zip/:id          subfolder as ZIP\nGET  /public/*                      static assets (logo, file-type icons)\n```\n\n## Reverse proxy\n\nAny TLS-terminating reverse proxy works. The proxy is a single HTTP\nlistener on the configured port, so the upstream config is trivial.\n\nnginx:\n\n```nginx\nlocation / {\n    proxy_pass http://localhost:3000;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n}\n```\n\nFor Traefik or Nginx Proxy Manager, point the host to the proxy container's\nport and let the manager handle the rest. No special config is needed for\nstreaming or large files; downloads and ZIPs use HTTP/1.1 chunked transfer.\n\n## Development\n\n```bash\nnpm install\ncp .env.example .env\n# edit .env\nnpm run dev\n```\n\n`npm run dev` uses `tsx watch` with Node's native `--env-file`, so saving a\nfile in `src/` reloads the server.\n\n## Security notes\n\n- The proxy holds no OxiCloud admin credentials. Share tokens are the only\n  authorization, same as on an exposed OxiCloud.\n- Tokens are validated with a strict regex before any upstream call.\n- POST body size is capped at 64 KiB (the only POST is the password form).\n- The unlock cookie issued by OxiCloud after a successful password verify\n  is `HttpOnly` and scoped per-share-token; the proxy passes it through\n  unmodified.\n- TLS is the responsibility of the reverse proxy in front. The proxy itself\n  speaks plain HTTP on a private port.\n\n## License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabnvle%2Foxicloud-public-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabnvle%2Foxicloud-public-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabnvle%2Foxicloud-public-proxy/lists"}