A simpler alternative to Nextcloud and ownCloud, built with TypeScript and Deno using Fresh. 🦕 🍋 https://bewcloud.com/
Find a file
2025-08-23 08:10:59 +01:00
.do Migrate email provider (from Brevo to generic SMTP) (#67) 2025-06-10 10:28:13 +01:00
.github Implement (optional) SSO via OIDC (OpenID Connect) (#64) 2025-06-05 18:10:40 +01:00
.vscode Make it public! 2024-03-16 08:40:24 +00:00
components Revert expense listing date format to en-US 2025-08-23 08:10:59 +01:00
crons Implement a more robust Config (#60) 2025-05-25 15:48:53 +01:00
db-migrations Public File Sharing (#72) 2025-06-20 12:04:16 +01:00
islands Fix timezone issues with expenses. 2025-08-22 12:55:10 +01:00
lib Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
radicale-config Add CardDav and CalDav servers (#80) 2025-07-20 10:35:32 +01:00
routes Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
static Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
.dockerignore Implement a more robust Config (#60) 2025-05-25 15:48:53 +01:00
.dvmrc Fix timezone display issues with formatted dates 2025-08-21 17:09:32 +01:00
.env.sample Fix timezone issues with expenses. 2025-08-22 12:55:10 +01:00
.gitignore Add CardDav and CalDav servers (#80) 2025-07-20 10:35:32 +01:00
bewcloud.config.sample.ts Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
deno.json Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
dev.ts Make it public! 2024-03-16 08:40:24 +00:00
docker-compose.dev.yml Add CardDav and CalDav servers (#80) 2025-07-20 10:35:32 +01:00
docker-compose.yml Revert expense listing date format to en-US 2025-08-23 08:10:59 +01:00
Dockerfile Fix timezone display issues with formatted dates 2025-08-21 17:09:32 +01:00
fresh.config.ts Implement a more robust Config (#60) 2025-05-25 15:48:53 +01:00
fresh.gen.ts Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
LICENSE Make it public! 2024-03-16 08:40:24 +00:00
main.ts Make it public! 2024-03-16 08:40:24 +00:00
main_test.ts Implement bulk delete in files 2024-09-02 16:09:30 +01:00
Makefile Make it public! 2024-03-16 08:40:24 +00:00
migrate-db.ts Fail loudly on connection error while running migrations 2025-07-11 09:14:17 +01:00
README.md Basic CardDav UI (Contacts) 2025-08-10 07:48:16 +01:00
render.yaml Update Deno, update Render deploy file 2024-12-26 11:54:42 +00:00
tailwind.config.ts Make it public! 2024-03-16 08:40:24 +00:00

bewCloud

This is the bewCloud app built using Fresh and deployed using docker compose.

If you're looking for the desktop sync app, it's at bewcloud-desktop.

If you're looking for the mobile app, it's at bewcloud-mobile.

Self-host it!

Deploy to DigitalOcean

Deploy to Render

Buy managed cloud (1 year)

Buy managed cloud (1 month)

Or on your own machine:

Download/copy docker-compose.yml, .env.sample as .env, bewcloud.config.sample.ts as bewcloud.config.ts, and radicale-config/config as radicale-config/config (if you're using CalDav/CardDav).

Note

1993:1993 below comes from deno's docker image where 1993 is the default user id in it. It might change in the future since I don't control it.

$ mkdir data-files data-radicale # local directories for storing user-uploaded files and radicale data
$ sudo chown -R 1993:1993 data-files # solves permission-related issues in the container with uploading files
$ docker compose up -d # makes the app available at http://localhost:8000
$ docker compose run --rm website bash -c "cd /app && make migrate-db" # initializes/updates the database (only needs to be executed the first time and on any data updates)

Alternatively, check the Development section below.

Important

Even with signups disabled (config.auth.allowSignups=false), the first signup will work and become an admin.

Sponsors

These are the amazing entities or individuals who are sponsoring this project for this current month. If you'd like to show up here, check the GitHub Sponsors page or make a donation above $50 ($100 to show up on the website)!

NLnet Foundation

Development

Requirements

Important

Don't forget to set up your .env file based on .env.sample. Don't forget to set up your bewcloud.config.ts file based on bewcloud.config.sample.ts.

  • This was tested with Deno's version stated in the .dvmrc file, though other versions may work.
  • For the postgres dependency (used when running locally or in CI), you should have Docker and docker compose installed.

Commands

$ docker compose -f docker-compose.dev.yml up # (optional) runs docker with postgres, locally
$ make migrate-db # runs any missing database migrations
$ make start # runs the app
$ make format # formats the code
$ make test # runs tests

Other less-used commands

$ make exec-db # runs psql inside the postgres container, useful for running direct development queries like `DROP DATABASE "bewcloud"; CREATE DATABASE "bewcloud";`
$ make build # generates all static files for production deploy

Structure

  • Routes defined at routes/.
  • Static files are defined at static/.
  • Frontend-only components are defined at components/.
  • Isomorphic components are defined at islands/.
  • Cron jobs are defined at crons/.
  • Reusable bits of code are defined at lib/.
  • Database migrations are defined at db-migrations/.

Deployment

Just push to the main branch.

How does Contacts/CardDav and Calendar/CalDav work?

CalDav/CardDav is now available since v2.3.0, using Radicale via Docker, which is already very efficient (and battle-tested). The client for CardDav is available since v2.4.0 and for CalDav is not yet implemented. Check this tag/release for custom-made server and clients where it was all mostly working, except for many edge cases.

In order to share a calendar, you can either have a shared user, or you can symlink the calendar to the user's own calendar (simply ln -s /<absolute-path-to-data-radicale>/collections/collection-root/<owner-user-id>/<calendar-to-share> /<absolute-path-to-data-radicale>/collections/collection-root/<user-id-to-share-with>/).

Note

If you're running radicale with docker, the symlink needs to point to the container's directory, usually starting with /data if you didn't change the radicale-config/config, otherwise the container will fail to load the linked directory.

How does private file sharing work?

Public file sharing is now possible since v2.2.0. Check this PR for advanced sharing with internal and external users, with read and write access that was being done and almost working. I ditched all that complexity for simply using symlinks for internal sharing, as it served my use case (I have multiple data backups and trust the people I provide accounts to, with the symlinks).

You can simply ln -s /<absolute-path-to-data-files>/<owner-user-id>/<directory-to-share> /<absolute-path-to-data-files>/<user-id-to-share-with>/ to create a shared directory between two users, and the same directory can have different names, now.

Note

If you're running the app with docker, the symlink needs to point to the container's directory, usually starting with /app if you didn't change the Dockerfile, otherwise the container will fail to load the linked directory.

How does it look?

Check the website for screenshots or the YouTube channel for 1-minute demos.