Self-hosting
You can self-host Briefkasten with Docker or manually by spinning up the Next.js app and Postgres on any host yourself. There are a few caveats to keep in mind with the self-hosted route, however. Depending on how okay you are with signing up for online services.
You can use any Postgres database you like, i.e. local, or hosted in the cloud. However, the object storage for bookmark screenshots is designed to work specifically with Supabase. That means, if you don't fill in the SUPABASE_*
environment variables, you will not have dynamic bookmark screenshots. Otherwise, the app works just fine completely self-hosted, for example with the Docker setup described below!
Docker
You can host the Briefkasten application entirely on your own via the included docker files.
This will result in your hosting two items:
- The
Briefkasten
Next.js application - The companion PostgreSQL database
Make sure you have
docker
anddocker-compose
installed.
Getting Started
- Clone the repository to your server.
git clone https://github.com/ndom91/briefkasten.git
- Setup the environment variables.
Make a copy of the .env.example
file and fill in at least the required variables with your favorite text editor. The example file has annotations for the variables.
cp .env.example .env
vim .env
2
DATABASE_URL
When using the local postgres container you should set the DATABASE_URL
environment variable to DATABASE_URL=postgres://bkAdmin:briefkasten@postgres:5432/briefkasten?sslmode=disable
- Start the docker-compose stack of applications
docker-compose up -d
- Setup the database
After starting the containers, you still have to manually apply the database schema. This is most easily done through the app container (bk-app
).
docker exec -it bk-app /bin/bash
// Inside the 'bk-app' container
pnpm db:push
2
3
4
- Now your application and database should be up and running at the default
http://localhost:3000
!
You can continue by putting localhost:3000
behind a reverse proxy (i.e. nginx
) which can terminate TLS for you (https) and provide access via a nice domain name of your choice. For more details, check out the Linode guide on setting up a reverse proxy with nginx.
Manually
To manually selfhost Briefkasten there are 3 required prerequisites and 1 optional one. The required items are as follows:
- A platform to host a Node.js (Next.js) application
- A Prisma compatible database (SQLite, Postgres, Mysql, etc.)
- An authentication provider
- S3-like object store (optional)
Next.js Hosting
To run the actual Briefkasten application itself, you will need some sort of platform to run a Node.js 16 application on. This can be any sort of server you have access to, or a hosting platform like Vercel or Netlify. I won't go into a ton of detail here, I will assume you know how to run a node.js application and/or can setup a Vercel account if you're going to be selfhosting software.
Some things to remember here, however, are the environment variables. You will need to make sure your hosting platform has a copy of your production environment variables. Including the production NEXTAUTH_URL
and NEXTAUTH_SECRET
. As well as a production DATABASE_URL
.
The OAuth credentials can be acquired through the instructions on the NextAuth.js site. Don't forget to set the provider clientId
/secret
of your choice (i.e. GITHUB_ID
/GITHUB_SECRET
).
Finally, if you've opted into providing an object storage provider for bookmark images, the application is currently setup to use Supabase only. Therefore, you can pass your secrets as SUPABASE_URL
and SUPABASE_KEY
. Make sure to use the service account key which has write
rights. More details below for using a different object storage provider.
Tip
The image uploading functionality will be skipped over entirely if you do not pass a SUPABASE_URL
environment variable. No other action is necessary.
Database
For the database portion, you must simply provide some write
permissioned credentials to any type of database supported by Prisma, preferably not MongoDB. This setting is applied primarily through the passing of the DATABASE_URL
which should contain all the details to connect, such as hostname and username/password. This environment variable is passed through to Prisma in its prisma/schema.prisma
file. Currently this file is setup for Postgres, therefore, if you plan to use a different type of database, **you must change the db.provider
value in that file from postgres
to whichever type you want.
After setting up your database credentials, you can run the following command to apply all migrations and prepare the database for the application.
pnpm dlx prisma migrate dev
# or
npx prisma migrate dev
2
3
After this, the database should be ready to receive new users and bookmarks from the application!
Authentication
For authentication, I've opted to use the NextAuth.js library, as I help maintain the project and am intimately familiar with it. Setup is extremely easy and I've prepared Briefkasten for the following 3 login types. You must use at least one and at most all 3. Although you can obviously adjust the code to add any more that you may wish to use.
The two OAuth providers are setup simply by passing their respective clientId
and secret
's via environment variables. The email magic link provider requires just an SMTP connection string, similar to the DATABASE_URL
connection string used previously. It should contain the SMTP host, username and password, port, etc. and can be supplied via the SMTP_SERVER
environment variable.
Object Storage
As previously mentioned, the object storage is optional, and used only for storing bookmark screenshots. The application with function just fine without bookmark images, however, in my opinion it will be much less nice 😃
Briefkasten is setup to use Supabase and their Storage product. You can sign-up for a free Supabase account at their website and use the 1GB free storage they provide you. As mentioned in the hosting section, you then simply need to pass the SUPABASE_URL
and SUPABASE_KEY
as environment variables for it to work.
If you want to use a different object storage provider, there are a few changes you will need to make. Including swapping out the use of the supabase
javascript sdk with your own object storage library, and replacing of the public bucket URL in a few places.
First, in /src/pages/api/bookmarks/index.js
, on L184
we are using the supabase
sdk client to upload the screenshot blob returned from the Briefkasten screenshot API. On L394
we are using the same sdk client in the DELETE
endpoint handler to delete images when their bookmark is deleted as well.
Secondly, in the /src/pages/api/bookmarks/uploadImage.js
on L25
in the PUT
handler, we are uploading the body of the PUT
request (which should be a base64 encoded image) to Supabase using their sdk client.
Those are the only usages of the sdk client which you would theoretically need to replace with the upload logic of another object storage provider.
In addition, there is hard coded the prefix of my Supabase bucket URL in a few places in the codebase. If you search for supabase.co/storage
, you will find all places (4) which need to be replace with the URL / static part of the URL of your new provider. Be aware the bucket must be public, or you must also add code to authenticate reads.